Rizin
unix-like reverse engineering framework and cli tools
parser.c File Reference
#include "runtime/parser.h"
#include <assert.h>
#include <stdio.h>
#include <limits.h>
#include <stdbool.h>
#include "tree_sitter/runtime.h"
#include "runtime/tree.h"
#include "runtime/lexer.h"
#include "runtime/length.h"
#include "runtime/array.h"
#include "runtime/language.h"
#include "runtime/alloc.h"
#include "runtime/reduce_action.h"
#include "runtime/error_costs.h"

Go to the source code of this file.

Classes

struct  ErrorRepairSession
 
struct  SkipPrecedingTreesSession
 

Macros

#define LOG(...)
 
#define LOG_STACK()
 
#define LOG_TREE()
 
#define SYM_NAME(symbol)   ts_language_symbol_name(self->language, symbol)
 

Typedefs

typedef int CondenseResult
 

Functions

static void parser__push (Parser *self, StackVersion version, Tree *tree, TSStateId state)
 
static bool parser__breakdown_top_of_stack (Parser *self, StackVersion version)
 
static bool parser__breakdown_lookahead (Parser *self, Tree **lookahead, TSStateId state, ReusableNode *reusable_node)
 
static bool ts_lex_mode_eq (TSLexMode self, TSLexMode other)
 
static bool parser__can_reuse (Parser *self, TSStateId state, Tree *tree, TableEntry *table_entry)
 
static CondenseResult parser__condense_stack (Parser *self)
 
static void parser__restore_external_scanner (Parser *self, StackVersion version)
 
static Tree * parser__lex (Parser *self, StackVersion version)
 
static void parser__clear_cached_token (Parser *self)
 
static Tree * parser__get_lookahead (Parser *self, StackVersion version, ReusableNode *reusable_node, bool *is_fresh)
 
static bool parser__select_tree (Parser *self, Tree *left, Tree *right)
 
static bool parser__better_version_exists (Parser *self, StackVersion version, ErrorStatus my_error_status)
 
static void parser__shift (Parser *self, StackVersion version, TSStateId state, Tree *lookahead, bool extra)
 
static bool parser__switch_children (Parser *self, Tree *tree, Tree **children, uint32_t count)
 
static StackPopResult parser__reduce (Parser *self, StackVersion version, TSSymbol symbol, unsigned count, bool fragile, bool allow_skipping)
 
static const TSParseActionparser__reductions_after_sequence (Parser *self, TSStateId start_state, const TreeArray *trees_below, uint32_t tree_count_below, const TreeArray *trees_above, TSSymbol lookahead_symbol, uint32_t *count)
 
static StackIterateAction parser__repair_error_callback (void *payload, TSStateId state, TreeArray *trees, uint32_t tree_count, bool is_done, bool is_pending)
 
static bool parser__repair_error (Parser *self, StackSlice slice, TSSymbol lookahead_symbol, TableEntry entry)
 
static void parser__start (Parser *self, TSInput input, Tree *previous_tree)
 
static void parser__accept (Parser *self, StackVersion version, Tree *lookahead)
 
static bool parser__do_potential_reductions (Parser *self, StackVersion version)
 
static StackIterateAction parser__skip_preceding_trees_callback (void *payload, TSStateId state, TreeArray *trees, uint32_t tree_count, bool is_done, bool is_pending)
 
static bool parser__skip_preceding_trees (Parser *self, StackVersion version, TSSymbol lookahead_symbol)
 
static void parser__handle_error (Parser *self, StackVersion version, TSSymbol lookahead_symbol)
 
static void parser__halt_parse (Parser *self)
 
static void parser__recover (Parser *self, StackVersion version, TSStateId state, Tree *lookahead)
 
static void parser__advance (Parser *self, StackVersion version, ReusableNode *reusable_node)
 
bool parser_init (Parser *self)
 
void parser_set_language (Parser *self, const TSLanguage *language)
 
void parser_destroy (Parser *self)
 
Tree * parser_parse (Parser *self, TSInput input, Tree *old_tree, bool halt_on_error)
 

Variables

static int CondenseResultMadeChange = 1
 
static int CondenseResultAllVersionsHadError = 2
 

Macro Definition Documentation

◆ LOG

#define LOG (   ...)
Value:
if (self->lexer.logger.log) { \
snprintf(self->lexer.debug_buffer, TS_DEBUG_BUFFER_SIZE, __VA_ARGS__); \
self->lexer.logger.log(self->lexer.logger.payload, TSLogTypeParse, \
self->lexer.debug_buffer); \
} \
if (self->print_debugging_graphs) { \
fprintf(stderr, "graph {\nlabel=\""); \
fprintf(stderr, __VA_ARGS__); \
fprintf(stderr, "\"\n}\n\n"); \
}
@ TSLogTypeParse
Definition: api.h:74

Definition at line 16 of file parser.c.

◆ LOG_STACK

#define LOG_STACK ( )
Value:
if (self->print_debugging_graphs) { \
ts_stack_print_dot_graph(self->stack, self->language->symbol_names, \
stderr); \
fputs("\n\n", stderr); \
}

Definition at line 28 of file parser.c.

◆ LOG_TREE

#define LOG_TREE ( )
Value:
if (self->print_debugging_graphs) { \
ts_tree_print_dot_graph(self->finished_tree, self->language, stderr); \
fputs("\n", stderr); \
}

Definition at line 35 of file parser.c.

◆ SYM_NAME

#define SYM_NAME (   symbol)    ts_language_symbol_name(self->language, symbol)

Definition at line 41 of file parser.c.

Typedef Documentation

◆ CondenseResult

Definition at line 154 of file parser.c.

Function Documentation

◆ parser__accept()

static void parser__accept ( Parser *  self,
StackVersion  version,
Tree *  lookahead 
)
static

Definition at line 815 of file parser.c.

816  {
817  lookahead->extra = true;
818  assert(lookahead->symbol == ts_builtin_sym_end);
819  ts_stack_push(self->stack, version, lookahead, false, 1);
820  StackPopResult pop = ts_stack_pop_all(self->stack, version);
821 
822  for (uint32_t i = 0; i < pop.slices.size; i++) {
823  StackSlice slice = pop.slices.contents[i];
824  TreeArray trees = slice.trees;
825 
826  Tree *root = NULL;
827  if (trees.size == 1) {
828  root = trees.contents[0];
829  array_delete(&trees);
830  } else {
831  for (uint32_t j = trees.size - 1; j + 1 > 0; j--) {
832  Tree *child = trees.contents[j];
833  if (!child->extra) {
834  root = ts_tree_make_copy(child);
835  root->child_count = 0;
836  for (uint32_t k = 0; k < child->child_count; k++)
837  ts_tree_retain(child->children[k]);
838  array_splice(&trees, j, 1, child->child_count, child->children);
839  ts_tree_set_children(root, trees.size, trees.contents);
840  ts_tree_release(child);
841  break;
842  }
843  }
844  }
845 
846  if (parser__select_tree(self, self->finished_tree, root)) {
847  ts_tree_release(self->finished_tree);
848  assert(root->ref_count > 0);
849  self->finished_tree = root;
850  } else {
851  ts_tree_release(root);
852  }
853  }
854 
855  ts_stack_remove_version(self->stack, pop.slices.contents[0].version);
856  ts_stack_halt(self->stack, version);
857 }
lzma_index ** i
Definition: index.h:629
#define array_delete(self)
Definition: array.h:41
#define array_splice(self, index, old_count, new_count, new_contents)
Definition: array.h:68
#define NULL
Definition: cris-opc.c:27
const char * k
Definition: dsignal.c:11
int root
Definition: enough.c:226
assert(limit<=UINT32_MAX/2)
#define ts_builtin_sym_end
Definition: parser.h:13
unsigned int uint32_t
Definition: sftypes.h:29
void ts_stack_halt(Stack *self, StackVersion version)
Definition: stack.c:705
void ts_stack_push(Stack *self, StackVersion version, Subtree subtree, bool pending, TSStateId state)
Definition: stack.c:485
void ts_stack_remove_version(Stack *self, StackVersion version)
Definition: stack.c:643
StackSliceArray ts_stack_pop_all(Stack *self, StackVersion version)
Definition: stack.c:569
static bool parser__select_tree(Parser *self, Tree *left, Tree *right)
Definition: parser.c:403

References array_delete, array_splice, assert(), i, k, NULL, parser__select_tree(), root, ts_builtin_sym_end, ts_stack_halt(), ts_stack_pop_all(), ts_stack_push(), and ts_stack_remove_version().

Referenced by parser__advance(), parser__halt_parse(), and parser__recover().

◆ parser__advance()

static void parser__advance ( Parser *  self,
StackVersion  version,
ReusableNode reusable_node 
)
static

Definition at line 1055 of file parser.c.

1056  {
1057  bool validated_lookahead = false;
1058  Tree *lookahead = parser__get_lookahead(self, version, reusable_node, &validated_lookahead);
1059 
1060  for (;;) {
1061  TSStateId state = ts_stack_top_state(self->stack, version);
1062 
1063  TableEntry table_entry;
1064  ts_language_table_entry(self->language, state, lookahead->first_leaf.symbol, &table_entry);
1065 
1066  if (!validated_lookahead) {
1067  if (!parser__can_reuse(self, state, lookahead, &table_entry)) {
1068  if (lookahead == reusable_node->tree) {
1069  reusable_node_pop_leaf(reusable_node);
1070  } else {
1072  }
1073 
1074  ts_tree_release(lookahead);
1075  lookahead = parser__get_lookahead(self, version, reusable_node, &validated_lookahead);
1076  continue;
1077  }
1078 
1079  validated_lookahead = true;
1080  LOG("reused_lookahead sym:%s, size:%u", SYM_NAME(lookahead->symbol), lookahead->size.bytes);
1081  }
1082 
1083  bool reduction_stopped_at_error = false;
1084  StackVersion last_reduction_version = STACK_VERSION_NONE;
1085 
1086  for (uint32_t i = 0; i < table_entry.action_count; i++) {
1087  TSParseAction action = table_entry.actions[i];
1088 
1089  switch (action.type) {
1090  case TSParseActionTypeShift: {
1091  bool extra = action.extra;
1092  TSStateId next_state;
1093 
1094  if (action.extra) {
1095  next_state = state;
1096  LOG("shift_extra");
1097  } else {
1098  next_state = action.params.to_state;
1099  LOG("shift state:%u", next_state);
1100  }
1101 
1102  if (lookahead->child_count > 0) {
1103  if (parser__breakdown_lookahead(self, &lookahead, state, reusable_node)) {
1104  if (!parser__can_reuse(self, state, lookahead, &table_entry)) {
1105  reusable_node_pop(reusable_node);
1106  ts_tree_release(lookahead);
1107  lookahead = parser__get_lookahead(self, version, reusable_node, &validated_lookahead);
1108  }
1109  }
1110 
1111  next_state = ts_language_next_state(self->language, state, lookahead->symbol);
1112  }
1113 
1114  parser__shift(self, version, next_state, lookahead, extra);
1115 
1116  if (lookahead == reusable_node->tree)
1117  reusable_node_pop(reusable_node);
1118 
1119  ts_tree_release(lookahead);
1120  return;
1121  }
1122 
1123  case TSParseActionTypeReduce: {
1124  if (reduction_stopped_at_error)
1125  continue;
1126 
1127  unsigned child_count = action.params.child_count;
1128  TSSymbol symbol = action.params.symbol;
1129  bool fragile = action.fragile;
1130 
1131  LOG("reduce sym:%s, child_count:%u", SYM_NAME(symbol), child_count);
1132 
1133  StackPopResult reduction =
1134  parser__reduce(self, version, symbol, child_count, fragile, true);
1135  StackSlice slice = *array_front(&reduction.slices);
1136  if (reduction.stopped_at_error) {
1137  reduction_stopped_at_error = true;
1138  if (!parser__repair_error(self, slice, lookahead->first_leaf.symbol,
1139  table_entry))
1140  break;
1141  }
1142 
1143  last_reduction_version = slice.version;
1144  break;
1145  }
1146 
1147  case TSParseActionTypeAccept: {
1148  if (ts_stack_error_status(self->stack, version).count > 0)
1149  continue;
1150 
1151  LOG("accept");
1152  parser__accept(self, version, lookahead);
1153  ts_tree_release(lookahead);
1154  return;
1155  }
1156 
1157  case TSParseActionTypeRecover: {
1158  while (lookahead->child_count > 0) {
1159  reusable_node_breakdown(reusable_node);
1160  ts_tree_release(lookahead);
1161  lookahead = reusable_node->tree;
1162  ts_tree_retain(lookahead);
1163  }
1164 
1165  parser__recover(self, version, action.params.to_state, lookahead);
1166  if (lookahead == reusable_node->tree)
1167  reusable_node_pop(reusable_node);
1168  ts_tree_release(lookahead);
1169  return;
1170  }
1171  }
1172  }
1173 
1174  if (last_reduction_version != STACK_VERSION_NONE) {
1175  ts_stack_renumber_version(self->stack, last_reduction_version, version);
1176  LOG_STACK();
1177  continue;
1178  }
1179 
1181  continue;
1182  }
1183 
1184  if (state == ERROR_STATE) {
1185  parser__push(self, version, lookahead, ERROR_STATE);
1186  return;
1187  }
1188 
1189  parser__handle_error(self, version, lookahead->first_leaf.symbol);
1190 
1191  if (ts_stack_is_halted(self->stack, version)) {
1192  ts_tree_release(lookahead);
1193  return;
1194  }
1195  }
1196 }
#define array_front(self)
Definition: array.h:31
#define ERROR_STATE
Definition: error_costs.h:4
void ts_language_table_entry(const TSLanguage *self, TSStateId state, TSSymbol symbol, TableEntry *result)
Definition: language.c:18
static TSStateId ts_language_next_state(const TSLanguage *self, TSStateId state, TSSymbol symbol)
Definition: language.h:181
uint16_t TSStateId
Definition: parser.h:16
@ TSParseActionTypeAccept
Definition: parser.h:56
@ TSParseActionTypeShift
Definition: parser.h:54
@ TSParseActionTypeRecover
Definition: parser.h:57
@ TSParseActionTypeReduce
Definition: parser.h:55
uint16_t TSSymbol
Definition: parser.h:19
#define STACK_VERSION_NONE
Definition: stack.h:16
unsigned StackVersion
Definition: stack.h:15
StackVersion version
Definition: stack.h:20
uint32_t action_count
Definition: language.h:15
const TSParseAction * actions
Definition: language.h:14
Definition: dis.h:43
void ts_stack_renumber_version(Stack *self, StackVersion v1, StackVersion v2)
Definition: stack.c:648
bool ts_stack_is_halted(const Stack *self, StackVersion version)
Definition: stack.c:720
static StackPopResult parser__reduce(Parser *self, StackVersion version, TSSymbol symbol, unsigned count, bool fragile, bool allow_skipping)
Definition: parser.c:504
static void parser__handle_error(Parser *self, StackVersion version, TSSymbol lookahead_symbol)
Definition: parser.c:961
static void parser__clear_cached_token(Parser *self)
Definition: parser.c:332
static void parser__push(Parser *self, StackVersion version, Tree *tree, TSStateId state)
Definition: parser.c:59
#define LOG(...)
Definition: parser.c:16
static Tree * parser__get_lookahead(Parser *self, StackVersion version, ReusableNode *reusable_node, bool *is_fresh)
Definition: parser.c:337
static bool parser__breakdown_lookahead(Parser *self, Tree **lookahead, TSStateId state, ReusableNode *reusable_node)
Definition: parser.c:112
static void parser__shift(Parser *self, StackVersion version, TSStateId state, Tree *lookahead, bool extra)
Definition: parser.c:461
#define LOG_STACK()
Definition: parser.c:28
static bool parser__can_reuse(Parser *self, TSStateId state, Tree *tree, TableEntry *table_entry)
Definition: parser.c:138
#define SYM_NAME(symbol)
Definition: parser.c:41
static bool parser__breakdown_top_of_stack(Parser *self, StackVersion version)
Definition: parser.c:65
static bool parser__repair_error(Parser *self, StackSlice slice, TSSymbol lookahead_symbol, TableEntry entry)
Definition: parser.c:715
static void parser__recover(Parser *self, StackVersion version, TSStateId state, Tree *lookahead)
Definition: parser.c:1029
static void parser__accept(Parser *self, StackVersion version, Tree *lookahead)
Definition: parser.c:815

References test-lz4-speed::action, TableEntry::action_count, TableEntry::actions, array_front, ERROR_STATE, i, LOG, LOG_STACK, parser__accept(), parser__breakdown_lookahead(), parser__breakdown_top_of_stack(), parser__can_reuse(), parser__clear_cached_token(), parser__get_lookahead(), parser__handle_error(), parser__push(), parser__recover(), parser__reduce(), parser__repair_error(), parser__shift(), STACK_VERSION_NONE, SYM_NAME, ts_language_next_state(), ts_language_table_entry(), ts_stack_is_halted(), ts_stack_renumber_version(), TSParseActionTypeAccept, TSParseActionTypeRecover, TSParseActionTypeReduce, TSParseActionTypeShift, and StackSlice::version.

Referenced by parser_parse().

◆ parser__better_version_exists()

static bool parser__better_version_exists ( Parser *  self,
StackVersion  version,
ErrorStatus  my_error_status 
)
static

Definition at line 437 of file parser.c.

438  {
439  if (self->finished_tree &&
440  self->finished_tree->error_cost <= my_error_status.cost)
441  return true;
442 
443  for (StackVersion i = 0, n = ts_stack_version_count(self->stack); i < n; i++) {
444  if (i == version || ts_stack_is_halted(self->stack, i))
445  continue;
446 
447  switch (error_status_compare(my_error_status,
448  ts_stack_error_status(self->stack, i))) {
449  case -1:
450  LOG("halt_other version:%u", i);
451  ts_stack_halt(self->stack, i);
452  break;
453  case 1:
454  return true;
455  }
456  }
457 
458  return false;
459 }
int n
Definition: mipsasm.c:19
unsigned cost
Definition: parser.c:111
uint32_t ts_stack_version_count(const Stack *self)
Definition: stack.c:443

References ErrorStatus::cost, i, LOG, n, ts_stack_halt(), ts_stack_is_halted(), and ts_stack_version_count().

Referenced by parser__handle_error(), parser__recover(), parser__reduce(), and parser__repair_error().

◆ parser__breakdown_lookahead()

static bool parser__breakdown_lookahead ( Parser *  self,
Tree **  lookahead,
TSStateId  state,
ReusableNode reusable_node 
)
static

Definition at line 112 of file parser.c.

114  {
115  bool result = false;
116  while (reusable_node->tree->child_count > 0 &&
117  (self->is_split || reusable_node->tree->parse_state != state ||
118  reusable_node->tree->fragile_left ||
119  reusable_node->tree->fragile_right)) {
120  LOG("state_mismatch sym:%s", SYM_NAME(reusable_node->tree->symbol));
121  reusable_node_breakdown(reusable_node);
122  result = true;
123  }
124 
125  if (result) {
126  ts_tree_release(*lookahead);
127  ts_tree_retain(*lookahead = reusable_node->tree);
128  }
129 
130  return result;
131 }

References LOG, and SYM_NAME.

Referenced by parser__advance().

◆ parser__breakdown_top_of_stack()

static bool parser__breakdown_top_of_stack ( Parser *  self,
StackVersion  version 
)
static

Definition at line 65 of file parser.c.

65  {
66  bool did_break_down = false;
67  bool pending = false;
68 
69  do {
70  StackPopResult pop = ts_stack_pop_pending(self->stack, version);
71  if (!pop.slices.size)
72  break;
73 
74  did_break_down = true;
75  pending = false;
76  for (uint32_t i = 0; i < pop.slices.size; i++) {
77  StackSlice slice = pop.slices.contents[i];
78  TSStateId state = ts_stack_top_state(self->stack, slice.version);
79  Tree *parent = *array_front(&slice.trees);
80 
81  for (uint32_t j = 0; j < parent->child_count; j++) {
82  Tree *child = parent->children[j];
83  pending = child->child_count > 0;
84 
85  if (child->symbol == ts_builtin_sym_error) {
87  } else if (!child->extra) {
88  state = ts_language_next_state(self->language, state, child->symbol);
89  }
90 
91  ts_stack_push(self->stack, slice.version, child, pending, state);
92  }
93 
94  for (uint32_t j = 1; j < slice.trees.size; j++) {
95  Tree *tree = slice.trees.contents[j];
96  parser__push(self, slice.version, tree, state);
97  }
98 
99  LOG("breakdown_top_of_stack tree:%s", SYM_NAME(parent->symbol));
100  LOG_STACK();
101 
102  ts_stack_decrease_push_count(self->stack, slice.version,
103  parent->child_count + 1);
104  ts_tree_release(parent);
105  array_delete(&slice.trees);
106  }
107  } while (pending);
108 
109  return did_break_down;
110 }
#define ts_builtin_sym_error
Definition: parser.h:12
StackSliceArray ts_stack_pop_pending(Stack *self, StackVersion version)
Definition: stack.c:524

References array_delete, array_front, ERROR_STATE, i, LOG, LOG_STACK, parser__push(), SYM_NAME, ts_builtin_sym_error, ts_language_next_state(), ts_stack_pop_pending(), ts_stack_push(), and StackSlice::version.

Referenced by parser__advance(), and parser__get_lookahead().

◆ parser__can_reuse()

static bool parser__can_reuse ( Parser *  self,
TSStateId  state,
Tree *  tree,
TableEntry table_entry 
)
static

Definition at line 138 of file parser.c.

139  {
140  TSLexMode current_lex_mode = self->language->lex_modes[state];
141  if (ts_lex_mode_eq(tree->first_leaf.lex_mode, current_lex_mode))
142  return true;
143  if (current_lex_mode.external_lex_state != 0)
144  return false;
145  if (tree->size.bytes == 0)
146  return false;
147  if (!table_entry->is_reusable)
148  return false;
149  if (!table_entry->depends_on_lookahead)
150  return true;
151  return tree->child_count > 1 && tree->error_cost == 0;
152 }
uint16_t external_lex_state
Definition: parser.h:79
bool is_reusable
Definition: language.h:16
static bool ts_lex_mode_eq(TSLexMode self, TSLexMode other)
Definition: parser.c:133

References TSLexMode::external_lex_state, TableEntry::is_reusable, and ts_lex_mode_eq().

Referenced by parser__advance().

◆ parser__clear_cached_token()

static void parser__clear_cached_token ( Parser *  self)
static

Definition at line 332 of file parser.c.

332  {
333  ts_tree_release(self->cached_token);
334  self->cached_token = NULL;
335 }

References NULL.

Referenced by parser__advance(), and parser_parse().

◆ parser__condense_stack()

static CondenseResult parser__condense_stack ( Parser *  self)
static

Definition at line 158 of file parser.c.

158  {
159  CondenseResult result = 0;
160  bool has_version_without_errors = false;
161 
162  for (StackVersion i = 0; i < ts_stack_version_count(self->stack); i++) {
163  if (ts_stack_is_halted(self->stack, i)) {
164  ts_stack_remove_version(self->stack, i);
165  result |= CondenseResultMadeChange;
166  i--;
167  continue;
168  }
169 
170  ErrorStatus error_status = ts_stack_error_status(self->stack, i);
171  if (error_status.count == 0) has_version_without_errors = true;
172 
173  for (StackVersion j = 0; j < i; j++) {
174  if (ts_stack_merge(self->stack, j, i)) {
175  result |= CondenseResultMadeChange;
176  i--;
177  break;
178  }
179 
180  switch (error_status_compare(error_status,
181  ts_stack_error_status(self->stack, j))) {
182  case -1:
183  ts_stack_remove_version(self->stack, j);
184  result |= CondenseResultMadeChange;
185  i--;
186  j--;
187  break;
188  case 1:
189  ts_stack_remove_version(self->stack, i);
190  result |= CondenseResultMadeChange;
191  i--;
192  break;
193  }
194  }
195  }
196 
197  if (!has_version_without_errors && ts_stack_version_count(self->stack) > 0) {
199  }
200 
201  return result;
202 }
bool ts_stack_merge(Stack *self, StackVersion version1, StackVersion version2)
Definition: stack.c:679
int CondenseResult
Definition: parser.c:154
static int CondenseResultMadeChange
Definition: parser.c:155
static int CondenseResultAllVersionsHadError
Definition: parser.c:156

References CondenseResultAllVersionsHadError, CondenseResultMadeChange, i, ts_stack_is_halted(), ts_stack_merge(), ts_stack_remove_version(), and ts_stack_version_count().

Referenced by parser_parse().

◆ parser__do_potential_reductions()

static bool parser__do_potential_reductions ( Parser *  self,
StackVersion  version 
)
static

Definition at line 859 of file parser.c.

859  {
860  bool has_shift_action = false;
861  TSStateId state = ts_stack_top_state(self->stack, version);
862  uint32_t previous_version_count = ts_stack_version_count(self->stack);
863 
864  array_clear(&self->reduce_actions);
865  for (TSSymbol symbol = 0; symbol < self->language->token_count; symbol++) {
867  ts_language_table_entry(self->language, state, symbol, &entry);
868  for (uint32_t i = 0; i < entry.action_count; i++) {
869  TSParseAction action = entry.actions[i];
870  if (action.extra)
871  continue;
872  switch (action.type) {
875  has_shift_action = true;
876  break;
878  if (action.params.child_count > 0)
879  ts_reduce_action_set_add(&self->reduce_actions, (ReduceAction){
880  .symbol = action.params.symbol,
881  .count = action.params.child_count,
882  });
883  default:
884  break;
885  }
886  }
887  }
888 
889  bool did_reduce = false;
890  for (uint32_t i = 0; i < self->reduce_actions.size; i++) {
891  ReduceAction action = self->reduce_actions.contents[i];
892  StackPopResult reduction =
893  parser__reduce(self, version, action.symbol, action.count, true, false);
894  if (reduction.stopped_at_error) {
895  ts_tree_array_delete(&reduction.slices.contents[0].trees);
896  ts_stack_remove_version(self->stack, reduction.slices.contents[0].version);
897  continue;
898  } else {
899  did_reduce = true;
900  }
901  }
902 
903  if (did_reduce) {
904  if (has_shift_action) {
905  return true;
906  } else {
907  ts_stack_renumber_version(self->stack, previous_version_count, version);
908  return false;
909  }
910  } else {
911  return true;
912  }
913 }
#define array_clear(self)
Definition: array.h:35
static void ts_reduce_action_set_add(ReduceActionSet *self, ReduceAction new_action)
Definition: reduce_action.h:20
Definition: zipcmp.c:77

References test-lz4-speed::action, array_clear, i, parser__reduce(), ts_language_table_entry(), ts_reduce_action_set_add(), ts_stack_remove_version(), ts_stack_renumber_version(), ts_stack_version_count(), TSParseActionTypeRecover, TSParseActionTypeReduce, and TSParseActionTypeShift.

Referenced by parser__handle_error().

◆ parser__get_lookahead()

static Tree* parser__get_lookahead ( Parser *  self,
StackVersion  version,
ReusableNode reusable_node,
bool is_fresh 
)
static

Definition at line 337 of file parser.c.

339  {
340  Length position = ts_stack_top_position(self->stack, version);
341 
342  while (reusable_node->tree) {
343  if (reusable_node->byte_index > position.bytes) {
344  LOG("before_reusable_node sym:%s", SYM_NAME(reusable_node->tree->symbol));
345  break;
346  }
347 
348  if (reusable_node->byte_index < position.bytes) {
349  LOG("past_reusable sym:%s", SYM_NAME(reusable_node->tree->symbol));
350  reusable_node_pop(reusable_node);
351  continue;
352  }
353 
354  if (reusable_node->tree->has_changes) {
355  LOG("cant_reuse_changed tree:%s, size:%u",
356  SYM_NAME(reusable_node->tree->symbol),
357  reusable_node->tree->size.bytes);
358  if (!reusable_node_breakdown(reusable_node)) {
359  reusable_node_pop(reusable_node);
361  }
362  continue;
363  }
364 
365  if (reusable_node->tree->symbol == ts_builtin_sym_error) {
366  LOG("cant_reuse_error tree:%s, size:%u",
367  SYM_NAME(reusable_node->tree->symbol),
368  reusable_node->tree->size.bytes);
369  if (!reusable_node_breakdown(reusable_node)) {
370  reusable_node_pop(reusable_node);
372  }
373  continue;
374  }
375 
376  if (!ts_external_token_state_eq(
377  reusable_node->preceding_external_token_state,
378  ts_stack_external_token_state(self->stack, version))) {
379  LOG("cant_reuse_external_tokens tree:%s, size:%u",
380  SYM_NAME(reusable_node->tree->symbol),
381  reusable_node->tree->size.bytes);
382  if (!reusable_node_breakdown(reusable_node)) {
383  reusable_node_pop(reusable_node);
385  }
386  continue;
387  }
388 
389  Tree *result = reusable_node->tree;
390  ts_tree_retain(result);
391  return result;
392  }
393 
394  if (self->cached_token && position.bytes == self->cached_token_byte_index) {
395  ts_tree_retain(self->cached_token);
396  return self->cached_token;
397  }
398 
399  *is_fresh = true;
400  return parser__lex(self, version);
401 }
Definition: length.h:9
uint32_t bytes
Definition: length.h:10
static Tree * parser__lex(Parser *self, StackVersion version)
Definition: parser.c:220

References Length::bytes, LOG, parser__breakdown_top_of_stack(), parser__lex(), SYM_NAME, and ts_builtin_sym_error.

Referenced by parser__advance().

◆ parser__halt_parse()

static void parser__halt_parse ( Parser *  self)
static

Definition at line 1005 of file parser.c.

1005  {
1006  LOG("halting_parse");
1007  LOG_STACK();
1008 
1009  ts_lexer_advance_to_end(&self->lexer);
1010  Length remaining_length = length_sub(
1011  self->lexer.current_position,
1012  ts_stack_top_position(self->stack, 0)
1013  );
1014 
1015  Tree *filler_node = ts_tree_make_error(remaining_length, length_zero(), 0);
1016  filler_node->visible = false;
1017  parser__push(self, 0, filler_node, 0);
1018 
1019  TreeArray children = array_new();
1020  Tree *root_error = ts_tree_make_error_node(&children);
1021  parser__push(self, 0, root_error, 0);
1022 
1024  Tree *eof = ts_tree_make_leaf(ts_builtin_sym_end, length_zero(), length_zero(), metadata);
1025  parser__accept(self, 0, eof);
1026  ts_tree_release(eof);
1027 }
#define array_new()
Definition: array.h:25
TSSymbolMetadata ts_language_symbol_metadata(const TSLanguage *self, TSSymbol symbol)
Definition: language.c:38
static Length length_zero(void)
Definition: length.h:39
static Length length_sub(Length len1, Length len2)
Definition: length.h:32
void ts_lexer_advance_to_end(Lexer *self)
Definition: lexer.c:357

References array_new, length_sub(), length_zero(), LOG, LOG_STACK, parser__accept(), parser__push(), ts_builtin_sym_end, ts_language_symbol_metadata(), and ts_lexer_advance_to_end().

Referenced by parser_parse().

◆ parser__handle_error()

static void parser__handle_error ( Parser *  self,
StackVersion  version,
TSSymbol  lookahead_symbol 
)
static

Definition at line 961 of file parser.c.

962  {
963  // If there are other stack versions that are clearly better than this one,
964  // just halt this version.
965  ErrorStatus error_status = ts_stack_error_status(self->stack, version);
966  error_status.count++;
967  if (parser__better_version_exists(self, version, error_status)) {
968  ts_stack_halt(self->stack, version);
969  LOG("bail_on_error");
970  return;
971  }
972 
973  LOG("handle_error");
974 
975  // If the current lookahead symbol would have been valid in some previous
976  // state on the stack, create one stack version that repairs the error
977  // immediately by simply skipping all of the trees that came after that state.
978  if (parser__skip_preceding_trees(self, version, lookahead_symbol)) {
979  LOG("skip_preceding_trees");
980  LOG_STACK();
981  }
982 
983  // Perform any reductions that could have happened in this state, regardless
984  // of the lookahead.
985  uint32_t previous_version_count = ts_stack_version_count(self->stack);
986  for (StackVersion v = version; v < ts_stack_version_count(self->stack);) {
987  if (parser__do_potential_reductions(self, v)) {
988  if (v == version) {
989  v = previous_version_count;
990  } else {
991  v++;
992  }
993  }
994  }
995 
996  // Push a discontinuity onto the stack. Merge all of the stack versions that
997  // were created in the previous step.
998  ts_stack_push(self->stack, version, NULL, false, ERROR_STATE);
999  while (ts_stack_version_count(self->stack) > previous_version_count) {
1000  ts_stack_push(self->stack, previous_version_count, NULL, false, ERROR_STATE);
1001  assert(ts_stack_merge(self->stack, version, previous_version_count));
1002  }
1003 }
const char * v
Definition: dsignal.c:12
static bool parser__better_version_exists(Parser *self, StackVersion version, ErrorStatus my_error_status)
Definition: parser.c:437
static bool parser__do_potential_reductions(Parser *self, StackVersion version)
Definition: parser.c:859
static bool parser__skip_preceding_trees(Parser *self, StackVersion version, TSSymbol lookahead_symbol)
Definition: parser.c:937

References assert(), ERROR_STATE, LOG, LOG_STACK, NULL, parser__better_version_exists(), parser__do_potential_reductions(), parser__skip_preceding_trees(), ts_stack_halt(), ts_stack_merge(), ts_stack_push(), ts_stack_version_count(), and v.

Referenced by parser__advance().

◆ parser__lex()

static Tree* parser__lex ( Parser *  self,
StackVersion  version 
)
static

Definition at line 220 of file parser.c.

220  {
221  TSStateId parse_state = ts_stack_top_state(self->stack, version);
222  Length start_position = ts_stack_top_position(self->stack, version);
223  TSLexMode lex_mode = self->language->lex_modes[parse_state];
224  const bool *valid_external_tokens = ts_language_enabled_external_tokens(
225  self->language,
226  lex_mode.external_lex_state
227  );
228 
229  bool found_external_token = false;
230  bool found_error = false;
231  bool skipped_error = false;
232  int32_t first_error_character = 0;
233  Length error_start_position, error_end_position;
234  ts_lexer_reset(&self->lexer, start_position);
235 
236  for (;;) {
237  Length current_position = self->lexer.current_position;
238 
239  if (valid_external_tokens) {
240  LOG("lex_external state:%d, row:%u, column:%u", lex_mode.external_lex_state,
241  current_position.extent.row, current_position.extent.column);
243  ts_lexer_start(&self->lexer);
244  if (self->language->external_scanner.scan(self->external_scanner_payload,
245  &self->lexer.data, valid_external_tokens)) {
246  if (length_has_unknown_chars(self->lexer.token_end_position)) {
247  self->lexer.token_end_position = self->lexer.current_position;
248  }
249  if (lex_mode.lex_state != 0 ||
250  self->lexer.token_end_position.bytes > current_position.bytes) {
251  found_external_token = true;
252  break;
253  }
254  }
255  ts_lexer_reset(&self->lexer, current_position);
256  }
257 
258  LOG("lex_internal state:%d, row:%u, column:%u", lex_mode.lex_state,
259  current_position.extent.row, current_position.extent.column);
260  ts_lexer_start(&self->lexer);
261  if (self->language->lex_fn(&self->lexer.data, lex_mode.lex_state)) {
262  if (length_has_unknown_chars(self->lexer.token_end_position)) {
263  self->lexer.token_end_position = self->lexer.current_position;
264  }
265  break;
266  }
267 
268  if (!found_error) {
269  LOG("retry_in_error_mode");
270  found_error = true;
271  lex_mode = self->language->lex_modes[ERROR_STATE];
272  valid_external_tokens = ts_language_enabled_external_tokens(
273  self->language,
274  lex_mode.external_lex_state
275  );
276  ts_lexer_reset(&self->lexer, start_position);
277  continue;
278  }
279 
280  if (!skipped_error) {
281  LOG("skip_unrecognized_character");
282  skipped_error = true;
283  error_start_position = self->lexer.token_start_position;
284  error_end_position = self->lexer.token_start_position;
285  first_error_character = self->lexer.data.lookahead;
286  }
287 
288  if (self->lexer.current_position.bytes == error_end_position.bytes) {
289  if (self->lexer.data.lookahead == 0) {
290  self->lexer.data.result_symbol = ts_builtin_sym_error;
291  break;
292  }
293  self->lexer.data.advance(&self->lexer, false);
294  }
295 
296  error_end_position = self->lexer.current_position;
297  }
298 
299  Tree *result;
300  if (skipped_error) {
301  Length padding = length_sub(error_start_position, start_position);
302  Length size = length_sub(error_end_position, error_start_position);
303  result = ts_tree_make_error(size, padding, first_error_character);
304  } else {
305  TSSymbol symbol = self->lexer.data.result_symbol;
306  if (found_external_token) {
307  symbol = self->language->external_scanner.symbol_map[symbol];
308  }
309 
310  Length padding = length_sub(self->lexer.token_start_position, start_position);
311  Length size = length_sub(self->lexer.token_end_position, self->lexer.token_start_position);
312  TSSymbolMetadata metadata = ts_language_symbol_metadata(self->language, symbol);
313  result = ts_tree_make_leaf(symbol, padding, size, metadata);
314 
315  if (found_external_token) {
316  result->has_external_tokens = true;
317  result->has_external_token_state = true;
318  memset(result->external_token_state, 0, sizeof(TSExternalTokenState));
319  self->language->external_scanner.serialize(self->external_scanner_payload, result->external_token_state);
320  self->lexer.last_external_token_state = &result->external_token_state;
321  }
322  }
323 
324  result->bytes_scanned = self->lexer.current_position.bytes - start_position.bytes + 1;
325  result->parse_state = parse_state;
326  result->first_leaf.lex_mode = lex_mode;
327 
328  LOG("lexed_lookahead sym:%s, size:%u", SYM_NAME(result->symbol), result->size.bytes);
329  return result;
330 }
voidpf void uLong size
Definition: ioapi.h:138
static const bool * ts_language_enabled_external_tokens(const TSLanguage *self, unsigned external_scanner_state)
Definition: language.h:216
void ts_lexer_reset(Lexer *self, Length position)
Definition: lexer.c:316
void ts_lexer_start(Lexer *self)
Definition: lexer.c:322
return memset(p, 0, total)
int int32_t
Definition: sftypes.h:33
TSPoint extent
Definition: length.h:11
uint16_t lex_state
Definition: parser.h:78
uint32_t row
Definition: api.h:56
uint32_t column
Definition: api.h:57
static void parser__restore_external_scanner(Parser *self, StackVersion version)
Definition: parser.c:204

References Length::bytes, TSPoint::column, ERROR_STATE, Length::extent, TSLexMode::external_lex_state, length_sub(), TSLexMode::lex_state, LOG, memset(), parser__restore_external_scanner(), TSPoint::row, SYM_NAME, ts_builtin_sym_error, ts_language_enabled_external_tokens(), ts_language_symbol_metadata(), ts_lexer_reset(), and ts_lexer_start().

Referenced by parser__get_lookahead().

◆ parser__push()

static void parser__push ( Parser *  self,
StackVersion  version,
Tree *  tree,
TSStateId  state 
)
static

Definition at line 59 of file parser.c.

60  {
61  ts_stack_push(self->stack, version, tree, false, state);
62  ts_tree_release(tree);
63 }

References ts_stack_push().

Referenced by parser__advance(), parser__breakdown_top_of_stack(), parser__halt_parse(), parser__recover(), parser__reduce(), parser__repair_error(), and parser__skip_preceding_trees().

◆ parser__recover()

static void parser__recover ( Parser *  self,
StackVersion  version,
TSStateId  state,
Tree *  lookahead 
)
static

Definition at line 1029 of file parser.c.

1030  {
1031  if (lookahead->symbol == ts_builtin_sym_end) {
1032  LOG("recover_eof");
1033  TreeArray children = array_new();
1034  Tree *parent = ts_tree_make_error_node(&children);
1035  parser__push(self, version, parent, 1);
1036  parser__accept(self, version, lookahead);
1037  }
1038 
1039  LOG("recover state:%u", state);
1040 
1041  StackVersion new_version = ts_stack_copy_version(self->stack, version);
1042 
1043  parser__shift(
1044  self, new_version, ERROR_STATE, lookahead,
1045  ts_language_symbol_metadata(self->language, lookahead->symbol).extra);
1046  ErrorStatus error_status = ts_stack_error_status(self->stack, new_version);
1047  if (parser__better_version_exists(self, version, error_status)) {
1048  ts_stack_remove_version(self->stack, new_version);
1049  LOG("bail_on_recovery");
1050  }
1051 
1052  parser__shift(self, version, state, lookahead, false);
1053 }
StackVersion ts_stack_copy_version(Stack *self, StackVersion version)
Definition: stack.c:669

References array_new, ERROR_STATE, LOG, parser__accept(), parser__better_version_exists(), parser__push(), parser__shift(), ts_builtin_sym_end, ts_language_symbol_metadata(), ts_stack_copy_version(), and ts_stack_remove_version().

Referenced by parser__advance().

◆ parser__reduce()

static StackPopResult parser__reduce ( Parser *  self,
StackVersion  version,
TSSymbol  symbol,
unsigned  count,
bool  fragile,
bool  allow_skipping 
)
static

Definition at line 504 of file parser.c.

506  {
507  uint32_t initial_version_count = ts_stack_version_count(self->stack);
508 
509  StackPopResult pop = ts_stack_pop_count(self->stack, version, count);
510  if (pop.stopped_at_error)
511  return pop;
512 
513  const TSLanguage *language = self->language;
514  TSSymbolMetadata metadata = ts_language_symbol_metadata(language, symbol);
515 
516  for (uint32_t i = 0; i < pop.slices.size; i++) {
517  StackSlice slice = pop.slices.contents[i];
518 
519  // Extra tokens on top of the stack should not be included in this new parent
520  // node. They will be re-pushed onto the stack after the parent node is
521  // created and pushed.
522  uint32_t child_count = slice.trees.size;
523  while (child_count > 0 && slice.trees.contents[child_count - 1]->extra)
524  child_count--;
525 
526  Tree *parent = ts_tree_make_node(symbol, child_count, slice.trees.contents, metadata);
527 
528  // This pop operation may have caused multiple stack versions to collapse
529  // into one, because they all diverged from a common state. In that case,
530  // choose one of the arrays of trees to be the parent node's children, and
531  // delete the rest of the tree arrays.
532  while (i + 1 < pop.slices.size) {
533  StackSlice next_slice = pop.slices.contents[i + 1];
534  if (next_slice.version != slice.version)
535  break;
536  i++;
537 
538  uint32_t child_count = next_slice.trees.size;
539  while (child_count > 0 && next_slice.trees.contents[child_count - 1]->extra)
540  child_count--;
541 
542  if (parser__switch_children(self, parent, next_slice.trees.contents, child_count)) {
543  ts_tree_array_delete(&slice.trees);
544  slice = next_slice;
545  } else {
546  ts_tree_array_delete(&next_slice.trees);
547  }
548  }
549 
550  TSStateId state = ts_stack_top_state(self->stack, slice.version);
551  TSStateId next_state = ts_language_next_state(language, state, symbol);
552  if (fragile || self->is_split || pop.slices.size > 1 || initial_version_count > 1) {
553  parent->fragile_left = true;
554  parent->fragile_right = true;
555  parent->parse_state = TS_TREE_STATE_NONE;
556  } else {
557  parent->parse_state = state;
558  }
559 
560  // If this pop operation terminated at the end of an error region, then
561  // create two stack versions: one in which the parent node is interpreted
562  // normally, and one in which the parent node is skipped.
563  if (state == ERROR_STATE && allow_skipping && child_count > 1) {
564  StackVersion other_version = ts_stack_copy_version(self->stack, slice.version);
565 
566  ts_stack_push(self->stack, other_version, parent, false, ERROR_STATE);
567  for (uint32_t j = parent->child_count; j < slice.trees.size; j++) {
568  Tree *tree = slice.trees.contents[j];
569  ts_stack_push(self->stack, other_version, tree, false, ERROR_STATE);
570  }
571 
572  ErrorStatus error_status = ts_stack_error_status(self->stack, other_version);
573  if (parser__better_version_exists(self, version, error_status))
574  ts_stack_remove_version(self->stack, other_version);
575  }
576 
577  // Push the parent node onto the stack, along with any extra tokens that
578  // were previously on top of the stack.
579  parser__push(self, slice.version, parent, next_state);
580  for (uint32_t j = parent->child_count; j < slice.trees.size; j++) {
581  Tree *tree = slice.trees.contents[j];
582  parser__push(self, slice.version, tree, next_state);
583  }
584  }
585 
586  for (StackVersion i = initial_version_count; i < ts_stack_version_count(self->stack); i++) {
587  for (StackVersion j = initial_version_count; j < i; j++) {
588  if (ts_stack_merge(self->stack, j, i)) {
589  i--;
590  break;
591  }
592  }
593  }
594 
595  return pop;
596 }
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void count
Definition: sflib.h:98
StackSliceArray ts_stack_pop_count(Stack *self, StackVersion version, uint32_t count)
Definition: stack.c:507
#define TS_TREE_STATE_NONE
Definition: subtree.h:18
static bool parser__switch_children(Parser *self, Tree *tree, Tree **children, uint32_t count)
Definition: parser.c:485

References count, ERROR_STATE, i, parser__better_version_exists(), parser__push(), parser__switch_children(), ts_language_next_state(), ts_language_symbol_metadata(), ts_stack_copy_version(), ts_stack_merge(), ts_stack_pop_count(), ts_stack_push(), ts_stack_remove_version(), ts_stack_version_count(), TS_TREE_STATE_NONE, and StackSlice::version.

Referenced by parser__advance(), and parser__do_potential_reductions().

◆ parser__reductions_after_sequence()

static const TSParseAction* parser__reductions_after_sequence ( Parser *  self,
TSStateId  start_state,
const TreeArray *  trees_below,
uint32_t  tree_count_below,
const TreeArray *  trees_above,
TSSymbol  lookahead_symbol,
uint32_t count 
)
inlinestatic

Definition at line 598 of file parser.c.

601  {
603  uint32_t child_count = 0;
604  *count = 0;
605 
606  for (uint32_t i = 0; i < trees_below->size; i++) {
607  if (child_count == tree_count_below)
608  break;
609  Tree *tree = trees_below->contents[trees_below->size - 1 - i];
610  if (tree->extra) continue;
611  TSStateId next_state = ts_language_next_state(self->language, state, tree->symbol);
612  if (next_state == ERROR_STATE)
613  return NULL;
614  if (next_state != state) {
615  child_count++;
616  state = next_state;
617  }
618  }
619 
620  for (uint32_t i = 0; i < trees_above->size; i++) {
621  Tree *tree = trees_above->contents[i];
622  if (tree->extra) continue;
623  TSStateId next_state = ts_language_next_state(self->language, state, tree->symbol);
624  if (next_state == ERROR_STATE)
625  return NULL;
626  if (next_state != state) {
627  child_count++;
628  state = next_state;
629  }
630  }
631 
632  const TSParseAction *actions =
633  ts_language_actions(self->language, state, lookahead_symbol, count);
634 
635  if (*count > 0 && actions[*count - 1].type != TSParseActionTypeReduce) {
636  (*count)--;
637  }
638 
639  while (*count > 0 && actions[0].params.child_count < child_count) {
640  actions++;
641  (*count)--;
642  }
643 
644  while (*count > 0 && actions[*count - 1].params.child_count > child_count) {
645  (*count)--;
646  }
647 
648  return actions;
649 }
static const TSParseAction * ts_language_actions(const TSLanguage *self, TSStateId state, TSSymbol symbol, uint32_t *count)
Definition: language.h:45
static void start_state(RzCmdStateOutput *state)
Definition: rz-bin.c:13
int type
Definition: mipsasm.c:17

References TSParseAction::child_count, count, ERROR_STATE, i, NULL, start_state(), ts_language_actions(), ts_language_next_state(), TSParseActionTypeReduce, and type.

Referenced by parser__repair_error_callback().

◆ parser__repair_error()

static bool parser__repair_error ( Parser *  self,
StackSlice  slice,
TSSymbol  lookahead_symbol,
TableEntry  entry 
)
static

Definition at line 715 of file parser.c.

716  {
717  LOG("repair_error");
718  ErrorRepairSession session = {
719  .parser = self,
720  .lookahead_symbol = lookahead_symbol,
721  .found_repair = false,
722  .trees_above_error = &slice.trees,
723  .tree_count_above_error = ts_tree_array_essential_count(&slice.trees),
724  };
725 
726  array_clear(&self->reduce_actions);
727  for (uint32_t i = 0; i < entry.action_count; i++) {
728  if (entry.actions[i].type == TSParseActionTypeReduce) {
729  TSSymbol symbol = entry.actions[i].params.symbol;
730  uint32_t child_count = entry.actions[i].params.child_count;
731  if ((child_count > session.tree_count_above_error) ||
732  (child_count == session.tree_count_above_error &&
733  !ts_language_symbol_metadata(self->language, symbol).visible))
734  array_push(&self->reduce_actions, ((ReduceAction){
735  .symbol = symbol,
736  .count = child_count
737  }));
738  }
739  }
740 
741  StackPopResult pop = ts_stack_iterate(
742  self->stack, slice.version, parser__repair_error_callback, &session);
743 
744  if (!session.found_repair) {
745  LOG("no_repair_found");
746  ts_stack_remove_version(self->stack, slice.version);
747  ts_tree_array_delete(&slice.trees);
748  return false;
749  }
750 
751  ReduceAction repair = session.best_repair;
752  TSStateId next_state = session.best_repair_next_state;
753  uint32_t skip_count = session.best_repair_skip_count;
754  TSSymbol symbol = repair.symbol;
755 
756  StackSlice new_slice = array_pop(&pop.slices);
757  TreeArray children = new_slice.trees;
758  ts_stack_renumber_version(self->stack, new_slice.version, slice.version);
759 
760  for (uint32_t i = pop.slices.size - 1; i + 1 > 0; i--) {
761  StackSlice other_slice = pop.slices.contents[i];
762  ts_tree_array_delete(&other_slice.trees);
763  if (other_slice.version != pop.slices.contents[i + 1].version)
764  ts_stack_remove_version(self->stack, other_slice.version);
765  }
766 
767  TreeArray skipped_children = ts_tree_array_remove_last_n(&children, skip_count);
768  TreeArray trailing_extras = ts_tree_array_remove_trailing_extras(&skipped_children);
769  Tree *error = ts_tree_make_error_node(&skipped_children);
770  array_push(&children, error);
771  array_push_all(&children, &trailing_extras);
772  trailing_extras.size = 0;
773  array_delete(&trailing_extras);
774 
775  for (uint32_t i = 0; i < slice.trees.size; i++)
776  array_push(&children, slice.trees.contents[i]);
777  array_delete(&slice.trees);
778 
779  Tree *parent =
780  ts_tree_make_node(symbol, children.size, children.contents,
781  ts_language_symbol_metadata(self->language, symbol));
782  parser__push(self, slice.version, parent, next_state);
783  ts_stack_decrease_push_count(self->stack, slice.version, error->child_count);
784 
785  ErrorStatus error_status = ts_stack_error_status(self->stack, slice.version);
786  if (parser__better_version_exists(self, slice.version, error_status)) {
787  LOG("no_better_repair_found");
788  ts_stack_halt(self->stack, slice.version);
789  return false;
790  } else {
791  LOG("repair_found sym:%s, child_count:%u, cost:%u", SYM_NAME(symbol),
792  repair.count, parent->error_cost);
793  return true;
794  }
795 }
#define array_push_all(self, other)
Definition: array.h:54
#define array_push(self, element)
Definition: array.h:43
#define array_pop(self)
Definition: array.h:82
bool found_repair
Definition: parser.c:48
uint32_t tree_count_above_error
Definition: parser.c:47
Parser * parser
Definition: parser.c:44
uint32_t best_repair_skip_count
Definition: parser.c:51
ReduceAction best_repair
Definition: parser.c:49
TSStateId best_repair_next_state
Definition: parser.c:50
TSSymbol symbol
Definition: reduce_action.h:13
uint32_t count
Definition: reduce_action.h:12
bool visible
Definition: parser.h:36
static StackIterateAction parser__repair_error_callback(void *payload, TSStateId state, TreeArray *trees, uint32_t tree_count, bool is_done, bool is_pending)
Definition: parser.c:651
void error(const char *msg)
Definition: untgz.c:593

References array_clear, array_delete, array_pop, array_push, array_push_all, ErrorRepairSession::best_repair, ErrorRepairSession::best_repair_next_state, ErrorRepairSession::best_repair_skip_count, ReduceAction::count, error(), ErrorRepairSession::found_repair, i, LOG, ErrorRepairSession::parser, parser__better_version_exists(), parser__push(), parser__repair_error_callback(), SYM_NAME, ReduceAction::symbol, ErrorRepairSession::tree_count_above_error, ts_language_symbol_metadata(), ts_stack_halt(), ts_stack_remove_version(), ts_stack_renumber_version(), TSParseActionTypeReduce, StackSlice::version, and TSSymbolMetadata::visible.

Referenced by parser__advance().

◆ parser__repair_error_callback()

static StackIterateAction parser__repair_error_callback ( void *  payload,
TSStateId  state,
TreeArray *  trees,
uint32_t  tree_count,
bool  is_done,
bool  is_pending 
)
static

Definition at line 651 of file parser.c.

653  {
654 
655  ErrorRepairSession *session = (ErrorRepairSession *)payload;
656  Parser *self = session->parser;
657  TSSymbol lookahead_symbol = session->lookahead_symbol;
658  ReduceActionSet *repairs = &self->reduce_actions;
659  TreeArray *trees_above_error = session->trees_above_error;
660  uint32_t tree_count_above_error = session->tree_count_above_error;
661 
662  StackIterateAction result = StackIterateNone;
663 
664  uint32_t last_repair_count = -1;
665  uint32_t repair_reduction_count = -1;
666  const TSParseAction *repair_reductions = NULL;
667 
668  for (uint32_t i = 0; i < repairs->size; i++) {
669  ReduceAction *repair = &repairs->contents[i];
670  uint32_t count_needed_below_error = repair->count - tree_count_above_error;
671  if (count_needed_below_error > tree_count)
672  break;
673 
674  uint32_t skip_count = tree_count - count_needed_below_error;
675  if (session->found_repair && skip_count >= session->best_repair_skip_count) {
676  array_erase(repairs, i--);
677  continue;
678  }
679 
680  TSStateId state_after_repair = ts_language_next_state(self->language, state, repair->symbol);
681  if (state == ERROR_STATE || state_after_repair == ERROR_STATE)
682  continue;
683 
684  uint32_t action_count;
685  ts_language_actions(self->language, state_after_repair, lookahead_symbol, &action_count);
686  if (action_count == 0)
687  continue;
688 
689  if (count_needed_below_error != last_repair_count) {
690  last_repair_count = count_needed_below_error;
691  repair_reductions = parser__reductions_after_sequence(
692  self, state, trees, count_needed_below_error, trees_above_error,
693  lookahead_symbol, &repair_reduction_count);
694  }
695 
696  for (uint32_t j = 0; j < repair_reduction_count; j++) {
697  if (repair_reductions[j].params.symbol == repair->symbol) {
698  result |= StackIteratePop;
699  session->found_repair = true;
700  session->best_repair = *repair;
701  session->best_repair_skip_count = skip_count;
702  session->best_repair_next_state = state_after_repair;
703  array_erase(repairs, i--);
704  break;
705  }
706  }
707  }
708 
709  if (repairs->size == 0)
710  result |= StackIterateStop;
711 
712  return result;
713 }
#define array_erase(self, index)
Definition: array.h:79
TreeArray * trees_above_error
Definition: parser.c:46
TSSymbol lookahead_symbol
Definition: parser.c:45
static const TSParseAction * parser__reductions_after_sequence(Parser *self, TSStateId start_state, const TreeArray *trees_below, uint32_t tree_count_below, const TreeArray *trees_above, TSSymbol lookahead_symbol, uint32_t *count)
Definition: parser.c:598

References array_erase, ErrorRepairSession::best_repair, ErrorRepairSession::best_repair_next_state, ErrorRepairSession::best_repair_skip_count, ReduceAction::count, ERROR_STATE, ErrorRepairSession::found_repair, i, ErrorRepairSession::lookahead_symbol, NULL, ErrorRepairSession::parser, parser__reductions_after_sequence(), TSParseAction::symbol, ReduceAction::symbol, ErrorRepairSession::tree_count_above_error, ErrorRepairSession::trees_above_error, ts_language_actions(), and ts_language_next_state().

Referenced by parser__repair_error().

◆ parser__restore_external_scanner()

static void parser__restore_external_scanner ( Parser *  self,
StackVersion  version 
)
static

Definition at line 204 of file parser.c.

204  {
205  const TSExternalTokenState *state = ts_stack_external_token_state(self->stack, version);
206  if (self->lexer.last_external_token_state != state) {
207  LOG("restore_external_scanner");
208  self->lexer.last_external_token_state = state;
209  if (state) {
210  self->language->external_scanner.deserialize(
211  self->external_scanner_payload,
212  *state
213  );
214  } else {
215  self->language->external_scanner.reset(self->external_scanner_payload);
216  }
217  }
218 }

References LOG.

Referenced by parser__lex().

◆ parser__select_tree()

static bool parser__select_tree ( Parser *  self,
Tree *  left,
Tree *  right 
)
static

Definition at line 403 of file parser.c.

403  {
404  if (!left)
405  return true;
406  if (!right)
407  return false;
408  if (right->error_cost < left->error_cost) {
409  LOG("select_smaller_error symbol:%s, over_symbol:%s",
410  SYM_NAME(right->symbol), SYM_NAME(left->symbol));
411  return true;
412  }
413  if (left->error_cost < right->error_cost) {
414  LOG("select_smaller_error symbol:%s, over_symbol:%s",
415  SYM_NAME(left->symbol), SYM_NAME(right->symbol));
416  return false;
417  }
418 
419  int comparison = ts_tree_compare(left, right);
420  switch (comparison) {
421  case -1:
422  LOG("select_earlier symbol:%s, over_symbol:%s", SYM_NAME(left->symbol),
423  SYM_NAME(right->symbol));
424  return false;
425  break;
426  case 1:
427  LOG("select_earlier symbol:%s, over_symbol:%s", SYM_NAME(right->symbol),
428  SYM_NAME(left->symbol));
429  return true;
430  default:
431  LOG("select_existing symbol:%s, over_symbol:%s", SYM_NAME(left->symbol),
432  SYM_NAME(right->symbol));
433  return false;
434  }
435 }

References LOG, and SYM_NAME.

Referenced by parser__accept(), and parser__switch_children().

◆ parser__shift()

static void parser__shift ( Parser *  self,
StackVersion  version,
TSStateId  state,
Tree *  lookahead,
bool  extra 
)
static

Definition at line 461 of file parser.c.

462  {
463  if (extra != lookahead->extra) {
464  TSSymbolMetadata metadata =
465  ts_language_symbol_metadata(self->language, lookahead->symbol);
466  if (metadata.structural && ts_stack_version_count(self->stack) > 1) {
467  lookahead = ts_tree_make_copy(lookahead);
468  } else {
469  ts_tree_retain(lookahead);
470  }
471  lookahead->extra = extra;
472  } else {
473  ts_tree_retain(lookahead);
474  }
475 
476  bool is_pending = lookahead->child_count > 0;
477  ts_stack_push(self->stack, version, lookahead, is_pending, state);
478  if (lookahead->has_external_token_state) {
479  ts_stack_set_external_token_state(
480  self->stack, version, ts_tree_last_external_token_state(lookahead));
481  }
482  ts_tree_release(lookahead);
483 }

References ts_language_symbol_metadata(), ts_stack_push(), and ts_stack_version_count().

Referenced by parser__advance(), and parser__recover().

◆ parser__skip_preceding_trees()

static bool parser__skip_preceding_trees ( Parser *  self,
StackVersion  version,
TSSymbol  lookahead_symbol 
)
static

Definition at line 937 of file parser.c.

938  {
939  SkipPrecedingTreesSession session = { self, lookahead_symbol };
940  StackPopResult pop = ts_stack_iterate(
941  self->stack, version, parser__skip_preceding_trees_callback, &session);
942 
943  StackVersion previous_version = STACK_VERSION_NONE;
944  for (uint32_t i = 0; i < pop.slices.size; i++) {
945  StackSlice slice = pop.slices.contents[i];
946  if (slice.version == previous_version) {
947  ts_tree_array_delete(&slice.trees);
948  continue;
949  }
950 
951  previous_version = slice.version;
952  Tree *error = ts_tree_make_error_node(&slice.trees);
953  error->extra = true;
954  TSStateId state = ts_stack_top_state(self->stack, slice.version);
955  parser__push(self, slice.version, error, state);
956  }
957 
958  return pop.slices.size > 0;
959 }
static StackIterateAction parser__skip_preceding_trees_callback(void *payload, TSStateId state, TreeArray *trees, uint32_t tree_count, bool is_done, bool is_pending)
Definition: parser.c:915

References error(), i, parser__push(), parser__skip_preceding_trees_callback(), STACK_VERSION_NONE, and StackSlice::version.

Referenced by parser__handle_error().

◆ parser__skip_preceding_trees_callback()

static StackIterateAction parser__skip_preceding_trees_callback ( void *  payload,
TSStateId  state,
TreeArray *  trees,
uint32_t  tree_count,
bool  is_done,
bool  is_pending 
)
static

Definition at line 915 of file parser.c.

917  {
918  if (tree_count > 0 && state != ERROR_STATE) {
919  uint32_t bytes_skipped = 0;
920  for (uint32_t i = 0; i < trees->size; i++) {
921  bytes_skipped += ts_tree_total_bytes(trees->contents[i]);
922  }
923  if (bytes_skipped == 0) return StackIterateNone;
924  SkipPrecedingTreesSession *session = payload;
925  Parser *self = session->parser;
926  TSSymbol lookahead_symbol = session->lookahead_symbol;
927  uint32_t action_count;
928  const TSParseAction *actions =
929  ts_language_actions(self->language, state, lookahead_symbol, &action_count);
930  if (action_count > 0 && actions[0].type == TSParseActionTypeReduce) {
931  return StackIteratePop | StackIterateStop;
932  }
933  }
934  return StackIterateNone;
935 }
TSSymbol lookahead_symbol
Definition: parser.c:56

References ERROR_STATE, i, SkipPrecedingTreesSession::lookahead_symbol, SkipPrecedingTreesSession::parser, ts_language_actions(), TSParseActionTypeReduce, and type.

Referenced by parser__skip_preceding_trees().

◆ parser__start()

static void parser__start ( Parser *  self,
TSInput  input,
Tree *  previous_tree 
)
static

Definition at line 797 of file parser.c.

797  {
798  if (previous_tree) {
799  LOG("parse_after_edit");
800  } else {
801  LOG("new_parse");
802  }
803 
804  if (self->language->external_scanner.reset) {
805  self->language->external_scanner.reset(self->external_scanner_payload);
806  }
807 
808  ts_lexer_set_input(&self->lexer, input);
809  ts_stack_clear(self->stack);
810  self->reusable_node = reusable_node_new(previous_tree);
811  self->cached_token = NULL;
812  self->finished_tree = NULL;
813 }
void ts_lexer_set_input(Lexer *self, TSInput input)
Definition: lexer.c:308
static ReusableNode reusable_node_new(void)
Definition: reusable_node.h:14
void ts_stack_clear(Stack *self)
Definition: stack.c:737
static bool input(void *ud, zip_uint8_t *data, zip_uint64_t length)

References input(), LOG, NULL, reusable_node_new(), ts_lexer_set_input(), and ts_stack_clear().

Referenced by parser_parse().

◆ parser__switch_children()

static bool parser__switch_children ( Parser *  self,
Tree *  tree,
Tree **  children,
uint32_t  count 
)
static

Definition at line 485 of file parser.c.

486  {
487  self->scratch_tree.symbol = tree->symbol;
488  self->scratch_tree.child_count = 0;
489  ts_tree_set_children(&self->scratch_tree, count, children);
490  if (parser__select_tree(self, tree, &self->scratch_tree)) {
491  tree->size = self->scratch_tree.size;
492  tree->padding = self->scratch_tree.padding;
493  tree->error_cost = self->scratch_tree.error_cost;
494  tree->children = self->scratch_tree.children;
495  tree->child_count = self->scratch_tree.child_count;
496  tree->named_child_count = self->scratch_tree.named_child_count;
497  tree->visible_child_count = self->scratch_tree.visible_child_count;
498  return true;
499  } else {
500  return false;
501  }
502 }

References count, and parser__select_tree().

Referenced by parser__reduce().

◆ parser_destroy()

void parser_destroy ( Parser *  self)

Definition at line 1221 of file parser.c.

1221  {
1222  if (self->stack)
1223  ts_stack_delete(self->stack);
1224  if (self->reduce_actions.contents)
1225  array_delete(&self->reduce_actions);
1226  if (self->tree_path1.contents)
1227  array_delete(&self->tree_path1);
1228  if (self->tree_path2.contents)
1229  array_delete(&self->tree_path2);
1230  parser_set_language(self, NULL);
1231 }
void ts_stack_delete(Stack *self)
Definition: stack.c:424
void parser_set_language(Parser *self, const TSLanguage *language)
Definition: parser.c:1209

References array_delete, NULL, parser_set_language(), and ts_stack_delete().

◆ parser_init()

bool parser_init ( Parser *  self)

Definition at line 1198 of file parser.c.

1198  {
1199  ts_lexer_init(&self->lexer);
1200  array_init(&self->reduce_actions);
1201  array_init(&self->tree_path1);
1202  array_init(&self->tree_path2);
1203  array_grow(&self->reduce_actions, 4);
1204  self->stack = ts_stack_new();
1205  self->finished_tree = NULL;
1206  return true;
1207 }
#define array_init(self)
Definition: array.h:22
void ts_lexer_init(Lexer *self)
Definition: lexer.c:275
Stack * ts_stack_new(SubtreePool *subtree_pool)
Definition: stack.c:405

References array_init, NULL, ts_lexer_init(), and ts_stack_new().

◆ parser_parse()

Tree* parser_parse ( Parser *  self,
TSInput  input,
Tree *  old_tree,
bool  halt_on_error 
)

Definition at line 1233 of file parser.c.

1233  {
1234  parser__start(self, input, old_tree);
1235 
1237  uint32_t position = 0, last_position = 0;
1238  ReusableNode reusable_node;
1239 
1240  do {
1241  for (version = 0; version < ts_stack_version_count(self->stack); version++) {
1242  reusable_node = self->reusable_node;
1243  last_position = position;
1244 
1245  while (!ts_stack_is_halted(self->stack, version)) {
1246  position = ts_stack_top_position(self->stack, version).chars;
1247  if (position > last_position || (version > 0 && position == last_position))
1248  break;
1249 
1250  LOG("process version:%d, version_count:%u, state:%d, row:%u, col:%u",
1251  version, ts_stack_version_count(self->stack),
1252  ts_stack_top_state(self->stack, version),
1253  ts_stack_top_position(self->stack, version).extent.row,
1254  ts_stack_top_position(self->stack, version).extent.column);
1255 
1256  parser__advance(self, version, &reusable_node);
1257  LOG_STACK();
1258  }
1259  }
1260 
1261  self->reusable_node = reusable_node;
1262 
1263  CondenseResult condense_result = parser__condense_stack(self);
1264  if (halt_on_error && (condense_result & CondenseResultAllVersionsHadError)) {
1265  parser__halt_parse(self);
1266  break;
1267  }
1268 
1269  if (condense_result & CondenseResultMadeChange) {
1270  LOG("condense");
1271  LOG_STACK();
1272  }
1273 
1274  self->is_split = (version > 1);
1275  } while (version != 0);
1276 
1277  LOG("done");
1278  LOG_TREE();
1279  ts_stack_clear(self->stack);
1281  ts_tree_assign_parents(self->finished_tree, &self->tree_path1);
1282  return self->finished_tree;
1283 }
#define LOG_TREE()
Definition: parser.c:35
static void parser__halt_parse(Parser *self)
Definition: parser.c:1005
static void parser__start(Parser *self, TSInput input, Tree *previous_tree)
Definition: parser.c:797
static CondenseResult parser__condense_stack(Parser *self)
Definition: parser.c:158
static void parser__advance(Parser *self, StackVersion version, ReusableNode *reusable_node)
Definition: parser.c:1055

References CondenseResultAllVersionsHadError, CondenseResultMadeChange, input(), LOG, LOG_STACK, LOG_TREE, parser__advance(), parser__clear_cached_token(), parser__condense_stack(), parser__halt_parse(), parser__start(), STACK_VERSION_NONE, ts_stack_clear(), ts_stack_is_halted(), and ts_stack_version_count().

◆ parser_set_language()

void parser_set_language ( Parser *  self,
const TSLanguage language 
)

Definition at line 1209 of file parser.c.

1209  {
1210  if (self->external_scanner_payload && self->language->external_scanner.destroy)
1211  self->language->external_scanner.destroy(self->external_scanner_payload);
1212 
1213  if (language && language->external_scanner.create)
1214  self->external_scanner_payload = language->external_scanner.create();
1215  else
1216  self->external_scanner_payload = NULL;
1217 
1218  self->language = language;
1219 }
void *(* create)(void)
Definition: parser.h:120
struct TSLanguage::@436 external_scanner

References TSLanguage::create, TSLanguage::external_scanner, and NULL.

Referenced by parser_destroy().

◆ ts_lex_mode_eq()

static bool ts_lex_mode_eq ( TSLexMode  self,
TSLexMode  other 
)
inlinestatic

Definition at line 133 of file parser.c.

133  {
134  return self.lex_state == other.lex_state &&
135  self.external_lex_state == other.external_lex_state;
136 }

References TSLexMode::external_lex_state, and TSLexMode::lex_state.

Referenced by parser__can_reuse().

Variable Documentation

◆ CondenseResultAllVersionsHadError

int CondenseResultAllVersionsHadError = 2
static

Definition at line 156 of file parser.c.

Referenced by parser__condense_stack(), and parser_parse().

◆ CondenseResultMadeChange

int CondenseResultMadeChange = 1
static

Definition at line 155 of file parser.c.

Referenced by parser__condense_stack(), and parser_parse().