Rizin
unix-like reverse engineering framework and cli tools
subtree.c File Reference
#include <assert.h>
#include <ctype.h>
#include <limits.h>
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
#include "./alloc.h"
#include "./atomic.h"
#include "./subtree.h"
#include "./length.h"
#include "./language.h"
#include "./error_costs.h"
#include <stddef.h>

Go to the source code of this file.

Classes

struct  Edit
 

Macros

#define TS_MAX_INLINE_TREE_LENGTH   UINT8_MAX
 
#define TS_MAX_TREE_POOL_SIZE   32
 

Functions

void ts_external_scanner_state_init (ExternalScannerState *self, const char *data, unsigned length)
 
ExternalScannerState ts_external_scanner_state_copy (const ExternalScannerState *self)
 
void ts_external_scanner_state_delete (ExternalScannerState *self)
 
const char * ts_external_scanner_state_data (const ExternalScannerState *self)
 
bool ts_external_scanner_state_eq (const ExternalScannerState *a, const ExternalScannerState *b)
 
void ts_subtree_array_copy (SubtreeArray self, SubtreeArray *dest)
 
void ts_subtree_array_clear (SubtreePool *pool, SubtreeArray *self)
 
void ts_subtree_array_delete (SubtreePool *pool, SubtreeArray *self)
 
void ts_subtree_array_remove_trailing_extras (SubtreeArray *self, SubtreeArray *destination)
 
void ts_subtree_array_reverse (SubtreeArray *self)
 
SubtreePool ts_subtree_pool_new (uint32_t capacity)
 
void ts_subtree_pool_delete (SubtreePool *self)
 
static SubtreeHeapDatats_subtree_pool_allocate (SubtreePool *self)
 
static void ts_subtree_pool_free (SubtreePool *self, SubtreeHeapData *tree)
 
static bool ts_subtree_can_inline (Length padding, Length size, uint32_t lookahead_bytes)
 
Subtree ts_subtree_new_leaf (SubtreePool *pool, TSSymbol symbol, Length padding, Length size, uint32_t lookahead_bytes, TSStateId parse_state, bool has_external_tokens, bool depends_on_column, bool is_keyword, const TSLanguage *language)
 
void ts_subtree_set_symbol (MutableSubtree *self, TSSymbol symbol, const TSLanguage *language)
 
Subtree ts_subtree_new_error (SubtreePool *pool, int32_t lookahead_char, Length padding, Length size, uint32_t bytes_scanned, TSStateId parse_state, const TSLanguage *language)
 
MutableSubtree ts_subtree_clone (Subtree self)
 
MutableSubtree ts_subtree_make_mut (SubtreePool *pool, Subtree self)
 
static void ts_subtree__compress (MutableSubtree self, unsigned count, const TSLanguage *language, MutableSubtreeArray *stack)
 
void ts_subtree_balance (Subtree self, SubtreePool *pool, const TSLanguage *language)
 
void ts_subtree_summarize_children (MutableSubtree self, const TSLanguage *language)
 
MutableSubtree ts_subtree_new_node (TSSymbol symbol, SubtreeArray *children, unsigned production_id, const TSLanguage *language)
 
Subtree ts_subtree_new_error_node (SubtreeArray *children, bool extra, const TSLanguage *language)
 
Subtree ts_subtree_new_missing_leaf (SubtreePool *pool, TSSymbol symbol, Length padding, uint32_t lookahead_bytes, const TSLanguage *language)
 
void ts_subtree_retain (Subtree self)
 
void ts_subtree_release (SubtreePool *pool, Subtree self)
 
int ts_subtree_compare (Subtree left, Subtree right)
 
static void ts_subtree_set_has_changes (MutableSubtree *self)
 
Subtree ts_subtree_edit (Subtree self, const TSInputEdit *edit, SubtreePool *pool)
 
Subtree ts_subtree_last_external_token (Subtree tree)
 
static size_t ts_subtree__write_char_to_string (char *s, size_t n, int32_t c)
 
static void ts_subtree__write_dot_string (FILE *f, const char *string)
 
static size_t ts_subtree__write_to_string (Subtree self, char *string, size_t limit, const TSLanguage *language, bool include_all, TSSymbol alias_symbol, bool alias_is_named, const char *field_name)
 
char * ts_subtree_string (Subtree self, const TSLanguage *language, bool include_all)
 
void ts_subtree__print_dot_graph (const Subtree *self, uint32_t start_offset, const TSLanguage *language, TSSymbol alias_symbol, FILE *f)
 
void ts_subtree_print_dot_graph (Subtree self, const TSLanguage *language, FILE *f)
 
bool ts_subtree_external_scanner_state_eq (Subtree self, Subtree other)
 

Variables

static const ExternalScannerState empty_state = {{.short_data = {0}}, .length = 0}
 
static const char * ROOT_FIELD = "__ROOT__"
 

Macro Definition Documentation

◆ TS_MAX_INLINE_TREE_LENGTH

#define TS_MAX_INLINE_TREE_LENGTH   UINT8_MAX

Definition at line 21 of file subtree.c.

◆ TS_MAX_TREE_POOL_SIZE

#define TS_MAX_TREE_POOL_SIZE   32

Definition at line 22 of file subtree.c.

Function Documentation

◆ ts_external_scanner_state_copy()

ExternalScannerState ts_external_scanner_state_copy ( const ExternalScannerState self)

Definition at line 38 of file subtree.c.

38  {
39  ExternalScannerState result = *self;
40  if (self->length > sizeof(self->short_data)) {
41  result.long_data = ts_malloc(self->length);
42  memcpy(result.long_data, self->long_data, self->length);
43  }
44  return result;
45 }
#define ts_malloc
Definition: alloc.h:21
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
uint32_t length
Definition: subtree.h:36
char short_data[24]
Definition: subtree.h:34

References ExternalScannerState::long_data, memcpy(), and ts_malloc.

Referenced by ts_subtree_clone().

◆ ts_external_scanner_state_data()

const char* ts_external_scanner_state_data ( const ExternalScannerState self)

Definition at line 53 of file subtree.c.

53  {
54  if (self->length > sizeof(self->short_data)) {
55  return self->long_data;
56  } else {
57  return self->short_data;
58  }
59 }

Referenced by ts_external_scanner_state_eq(), ts_parser__restore_external_scanner(), and ts_stack_print_dot_graph().

◆ ts_external_scanner_state_delete()

void ts_external_scanner_state_delete ( ExternalScannerState self)

Definition at line 47 of file subtree.c.

47  {
48  if (self->length > sizeof(self->short_data)) {
49  ts_free(self->long_data);
50  }
51 }
#define ts_free
Definition: alloc.h:30

References ts_free.

Referenced by ts_subtree_release().

◆ ts_external_scanner_state_eq()

bool ts_external_scanner_state_eq ( const ExternalScannerState a,
const ExternalScannerState b 
)

Definition at line 61 of file subtree.c.

61  {
62  return a == b || (
63  a->length == b->length &&
65  );
66 }
#define b(i)
Definition: sha256.c:42
#define a(i)
Definition: sha256.c:41
const char * ts_external_scanner_state_data(const ExternalScannerState *self)
Definition: subtree.c:53

References a, b, and ts_external_scanner_state_data().

Referenced by ts_subtree_external_scanner_state_eq().

◆ ts_external_scanner_state_init()

void ts_external_scanner_state_init ( ExternalScannerState self,
const char *  data,
unsigned  length 
)

Definition at line 28 of file subtree.c.

28  {
29  self->length = length;
30  if (length > sizeof(self->short_data)) {
31  self->long_data = ts_malloc(length);
32  memcpy(self->long_data, data, length);
33  } else {
34  memcpy(self->short_data, data, length);
35  }
36 }
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 static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec struct timespec static rem const char static group const void length
Definition: sflib.h:133

References length, memcpy(), and ts_malloc.

Referenced by ts_parser__lex().

◆ ts_subtree__compress()

static void ts_subtree__compress ( MutableSubtree  self,
unsigned  count,
const TSLanguage language,
MutableSubtreeArray *  stack 
)
static

Definition at line 292 of file subtree.c.

297  {
298  unsigned initial_stack_size = stack->size;
299 
300  MutableSubtree tree = self;
301  TSSymbol symbol = tree.ptr->symbol;
302  for (unsigned i = 0; i < count; i++) {
303  if (tree.ptr->ref_count > 1 || tree.ptr->child_count < 2) break;
304 
306  if (
307  child.data.is_inline ||
308  child.ptr->child_count < 2 ||
309  child.ptr->ref_count > 1 ||
310  child.ptr->symbol != symbol
311  ) break;
312 
314  if (
315  grandchild.data.is_inline ||
316  grandchild.ptr->child_count < 2 ||
317  grandchild.ptr->ref_count > 1 ||
318  grandchild.ptr->symbol != symbol
319  ) break;
320 
321  ts_subtree_children(tree)[0] = ts_subtree_from_mut(grandchild);
322  ts_subtree_children(child)[0] = ts_subtree_children(grandchild)[grandchild.ptr->child_count - 1];
323  ts_subtree_children(grandchild)[grandchild.ptr->child_count - 1] = ts_subtree_from_mut(child);
324  array_push(stack, tree);
325  tree = grandchild;
326  }
327 
328  while (stack->size > initial_stack_size) {
329  tree = array_pop(stack);
332  ts_subtree_summarize_children(grandchild, language);
333  ts_subtree_summarize_children(child, language);
334  ts_subtree_summarize_children(tree, language);
335  }
336 }
lzma_index ** i
Definition: index.h:629
#define array_push(self, element)
Definition: array.h:43
#define array_pop(self)
Definition: array.h:82
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
uint16_t TSSymbol
Definition: parser.h:19
TSSymbol symbol
Definition: subtree.h:118
volatile uint32_t ref_count
Definition: subtree.h:112
uint32_t child_count
Definition: subtree.h:117
Definition: z80asm.h:140
void ts_subtree_summarize_children(MutableSubtree self, const TSLanguage *language)
Definition: subtree.c:371
#define ts_subtree_children(self)
Definition: subtree.h:233
static Subtree ts_subtree_from_mut(MutableSubtree self)
Definition: subtree.h:350
static MutableSubtree ts_subtree_to_mut_unsafe(Subtree self)
Definition: subtree.h:356
SubtreeHeapData * ptr
Definition: subtree.h:164
SubtreeInlineData data
Definition: subtree.h:163

References array_pop, array_push, SubtreeHeapData::child_count, count, MutableSubtree::data, i, SubtreeInlineData::is_inline, MutableSubtree::ptr, SubtreeHeapData::ref_count, SubtreeHeapData::symbol, ts_subtree_children, ts_subtree_from_mut(), ts_subtree_summarize_children(), and ts_subtree_to_mut_unsafe().

Referenced by ts_subtree_balance().

◆ ts_subtree__print_dot_graph()

void ts_subtree__print_dot_graph ( const Subtree self,
uint32_t  start_offset,
const TSLanguage language,
TSSymbol  alias_symbol,
FILE *  f 
)

Definition at line 967 of file subtree.c.

969  {
971  TSSymbol symbol = alias_symbol ? alias_symbol : subtree_symbol;
972  uint32_t end_offset = start_offset + ts_subtree_total_bytes(*self);
973  fprintf(f, "tree_%p [label=\"", (void *)self);
975  fprintf(f, "\"");
976 
977  if (ts_subtree_child_count(*self) == 0) fprintf(f, ", shape=plaintext");
978  if (ts_subtree_extra(*self)) fprintf(f, ", fontcolor=gray");
979 
980  fprintf(f, ", tooltip=\""
981  "range: %u - %u\n"
982  "state: %d\n"
983  "error-cost: %u\n"
984  "has-changes: %u\n"
985  "depends-on-column: %u\n"
986  "repeat-depth: %u\n"
987  "lookahead-bytes: %u",
988  start_offset, end_offset,
989  ts_subtree_parse_state(*self),
990  ts_subtree_error_cost(*self),
991  ts_subtree_has_changes(*self),
995  );
996 
997  if (ts_subtree_is_error(*self) && ts_subtree_child_count(*self) == 0) {
998  fprintf(f, "\ncharacter: '%c'", self->ptr->lookahead_char);
999  }
1000 
1001  fprintf(f, "\"]\n");
1002 
1003  uint32_t child_start_offset = start_offset;
1004  uint32_t child_info_offset =
1005  language->max_alias_sequence_length *
1006  ts_subtree_production_id(*self);
1007  for (uint32_t i = 0, n = ts_subtree_child_count(*self); i < n; i++) {
1008  const Subtree *child = &ts_subtree_children(*self)[i];
1009  TSSymbol alias_symbol = 0;
1010  if (!ts_subtree_extra(*child) && child_info_offset) {
1011  alias_symbol = language->alias_sequences[child_info_offset];
1012  child_info_offset++;
1013  }
1014  ts_subtree__print_dot_graph(child, child_start_offset, language, alias_symbol, f);
1015  fprintf(f, "tree_%p -> tree_%p [tooltip=%u]\n", (void *)self, (void *)child, i);
1016  child_start_offset += ts_subtree_total_bytes(*child);
1017  }
1018 }
const char * ts_language_symbol_name(const TSLanguage *, TSSymbol)
Definition: language.c:59
int n
Definition: mipsasm.c:19
unsigned int uint32_t
Definition: sftypes.h:29
#define f(i)
Definition: sha256.c:46
int32_t lookahead_char
Definition: subtree.h:151
const TSSymbol * alias_sequences
Definition: parser.h:112
uint16_t max_alias_sequence_length
Definition: parser.h:100
static void ts_subtree__write_dot_string(FILE *f, const char *string)
Definition: subtree.c:833
void ts_subtree__print_dot_graph(const Subtree *self, uint32_t start_offset, const TSLanguage *language, TSSymbol alias_symbol, FILE *f)
Definition: subtree.c:967
static uint32_t ts_subtree_total_bytes(Subtree self)
Definition: subtree.h:278
static uint32_t ts_subtree_error_cost(Subtree self)
Definition: subtree.h:302
static bool ts_subtree_extra(Subtree self)
Definition: subtree.h:216
static bool ts_subtree_is_error(Subtree self)
Definition: subtree.h:342
static bool ts_subtree_has_changes(Subtree self)
Definition: subtree.h:217
static uint16_t ts_subtree_production_id(Subtree self)
Definition: subtree.h:314
static uint32_t ts_subtree_repeat_depth(Subtree self)
Definition: subtree.h:286
static bool ts_subtree_depends_on_column(Subtree self)
Definition: subtree.h:334
static TSStateId ts_subtree_parse_state(Subtree self)
Definition: subtree.h:220
static uint32_t ts_subtree_lookahead_bytes(Subtree self)
Definition: subtree.h:221
static uint32_t ts_subtree_child_count(Subtree self)
Definition: subtree.h:282
static TSSymbol ts_subtree_symbol(Subtree self)
Definition: subtree.h:213
#define subtree_symbol(subtree, structural_child_index)
const SubtreeHeapData * ptr
Definition: subtree.h:158

References TSLanguage::alias_sequences, f, i, TSLanguage::max_alias_sequence_length, n, subtree_symbol, ts_language_symbol_name(), ts_subtree__write_dot_string(), ts_subtree_child_count(), ts_subtree_children, ts_subtree_depends_on_column(), ts_subtree_error_cost(), ts_subtree_extra(), ts_subtree_has_changes(), ts_subtree_is_error(), ts_subtree_lookahead_bytes(), ts_subtree_parse_state(), ts_subtree_production_id(), ts_subtree_repeat_depth(), ts_subtree_symbol(), and ts_subtree_total_bytes().

Referenced by ts_subtree_print_dot_graph().

◆ ts_subtree__write_char_to_string()

static size_t ts_subtree__write_char_to_string ( char *  s,
size_t  n,
int32_t  c 
)
static

Definition at line 816 of file subtree.c.

816  {
817  if (c == -1)
818  return snprintf(s, n, "INVALID");
819  else if (c == '\0')
820  return snprintf(s, n, "'\\0'");
821  else if (c == '\n')
822  return snprintf(s, n, "'\\n'");
823  else if (c == '\t')
824  return snprintf(s, n, "'\\t'");
825  else if (c == '\r')
826  return snprintf(s, n, "'\\r'");
827  else if (0 < c && c < 128 && isprint(c))
828  return snprintf(s, n, "'%c'", c);
829  else
830  return snprintf(s, n, "%d", c);
831 }
snprintf
Definition: kernel.h:364
static RzSocket * s
Definition: rtr.c:28
#define isprint(c)
Definition: safe-ctype.h:137
#define c(i)
Definition: sha256.c:43

References c, isprint, n, s, and snprintf.

Referenced by ts_subtree__write_to_string().

◆ ts_subtree__write_dot_string()

static void ts_subtree__write_dot_string ( FILE *  f,
const char *  string 
)
static

Definition at line 833 of file subtree.c.

833  {
834  for (const char *c = string; *c; c++) {
835  if (*c == '"') {
836  fputs("\\\"", f);
837  } else if (*c == '\n') {
838  fputs("\\n", f);
839  } else {
840  fputc(*c, f);
841  }
842  }
843 }

References c, and f.

Referenced by ts_subtree__print_dot_graph().

◆ ts_subtree__write_to_string()

static size_t ts_subtree__write_to_string ( Subtree  self,
char *  string,
size_t  limit,
const TSLanguage language,
bool  include_all,
TSSymbol  alias_symbol,
bool  alias_is_named,
const char *  field_name 
)
static

Definition at line 847 of file subtree.c.

851  {
852  if (!self.ptr) return snprintf(string, limit, "(NULL)");
853 
854  char *cursor = string;
855  char **writer = (limit > 1) ? &cursor : &string;
856  bool is_root = field_name == ROOT_FIELD;
857  bool is_visible =
858  include_all ||
859  ts_subtree_missing(self) ||
860  (
861  alias_symbol
862  ? alias_is_named
863  : ts_subtree_visible(self) && ts_subtree_named(self)
864  );
865 
866  if (is_visible) {
867  if (!is_root) {
868  cursor += snprintf(*writer, limit, " ");
869  if (field_name) {
870  cursor += snprintf(*writer, limit, "%s: ", field_name);
871  }
872  }
873 
874  if (ts_subtree_is_error(self) && ts_subtree_child_count(self) == 0 && self.ptr->size.bytes > 0) {
875  cursor += snprintf(*writer, limit, "(UNEXPECTED ");
876  cursor += ts_subtree__write_char_to_string(*writer, limit, self.ptr->lookahead_char);
877  } else {
878  TSSymbol symbol = alias_symbol ? alias_symbol : ts_subtree_symbol(self);
879  const char *symbol_name = ts_language_symbol_name(language, symbol);
880  if (ts_subtree_missing(self)) {
881  cursor += snprintf(*writer, limit, "(MISSING ");
882  if (alias_is_named || ts_subtree_named(self)) {
883  cursor += snprintf(*writer, limit, "%s", symbol_name);
884  } else {
885  cursor += snprintf(*writer, limit, "\"%s\"", symbol_name);
886  }
887  } else {
888  cursor += snprintf(*writer, limit, "(%s", symbol_name);
889  }
890  }
891  } else if (is_root) {
892  TSSymbol symbol = ts_subtree_symbol(self);
893  const char *symbol_name = ts_language_symbol_name(language, symbol);
894  cursor += snprintf(*writer, limit, "(\"%s\")", symbol_name);
895  }
896 
897  if (ts_subtree_child_count(self)) {
898  const TSSymbol *alias_sequence = ts_language_alias_sequence(language, self.ptr->production_id);
899  const TSFieldMapEntry *field_map, *field_map_end;
901  language,
902  self.ptr->production_id,
903  &field_map,
904  &field_map_end
905  );
906 
907  uint32_t structural_child_index = 0;
908  for (uint32_t i = 0; i < self.ptr->child_count; i++) {
909  Subtree child = ts_subtree_children(self)[i];
910  if (ts_subtree_extra(child)) {
911  cursor += ts_subtree__write_to_string(
912  child, *writer, limit,
913  language, include_all,
914  0, false, NULL
915  );
916  } else {
917  TSSymbol alias_symbol = alias_sequence
918  ? alias_sequence[structural_child_index]
919  : 0;
920  bool alias_is_named = alias_symbol
921  ? ts_language_symbol_metadata(language, alias_symbol).named
922  : false;
923 
924  const char *child_field_name = is_visible ? NULL : field_name;
925  for (const TSFieldMapEntry *i = field_map; i < field_map_end; i++) {
926  if (!i->inherited && i->child_index == structural_child_index) {
927  child_field_name = language->field_names[i->field_id];
928  break;
929  }
930  }
931 
932  cursor += ts_subtree__write_to_string(
933  child, *writer, limit,
934  language, include_all,
935  alias_symbol, alias_is_named, child_field_name
936  );
937  structural_child_index++;
938  }
939  }
940  }
941 
942  if (is_visible) cursor += snprintf(*writer, limit, ")");
943 
944  return cursor - string;
945 }
#define NULL
Definition: cris-opc.c:27
TSSymbolMetadata ts_language_symbol_metadata(const TSLanguage *self, TSSymbol symbol)
Definition: language.c:38
static void ts_language_field_map(const TSLanguage *self, uint32_t production_id, const TSFieldMapEntry **start, const TSFieldMapEntry **end)
Definition: language.h:246
static const TSSymbol * ts_language_alias_sequence(const TSLanguage *self, uint32_t production_id)
Definition: language.h:227
static uint32_t const uint8_t uint32_t uint32_t limit
Definition: memcmplen.h:45
@ field_name
Definition: parser.c:1737
const char *const * field_names
Definition: parser.h:106
void writer(void *n)
Definition: main.c:22
static size_t ts_subtree__write_char_to_string(char *s, size_t n, int32_t c)
Definition: subtree.c:816
static size_t ts_subtree__write_to_string(Subtree self, char *string, size_t limit, const TSLanguage *language, bool include_all, TSSymbol alias_symbol, bool alias_is_named, const char *field_name)
Definition: subtree.c:847
static const char * ROOT_FIELD
Definition: subtree.c:845
static bool ts_subtree_visible(Subtree self)
Definition: subtree.h:214
static bool ts_subtree_missing(Subtree self)
Definition: subtree.h:218
static bool ts_subtree_named(Subtree self)
Definition: subtree.h:215

References field_name, TSLanguage::field_names, i, limit, TSSymbolMetadata::named, NULL, ROOT_FIELD, snprintf, ts_language_alias_sequence(), ts_language_field_map(), ts_language_symbol_metadata(), ts_language_symbol_name(), ts_subtree__write_char_to_string(), ts_subtree_child_count(), ts_subtree_children, ts_subtree_extra(), ts_subtree_is_error(), ts_subtree_missing(), ts_subtree_named(), ts_subtree_symbol(), ts_subtree_visible(), and writer().

Referenced by ts_subtree_string().

◆ ts_subtree_array_clear()

void ts_subtree_array_clear ( SubtreePool pool,
SubtreeArray *  self 
)

Definition at line 83 of file subtree.c.

83  {
84  for (uint32_t i = 0; i < self->size; i++) {
85  ts_subtree_release(pool, self->contents[i]);
86  }
87  array_clear(self);
88 }
#define array_clear(self)
Definition: array.h:35
void ts_subtree_release(SubtreePool *pool, Subtree self)
Definition: subtree.c:584

References array_clear, i, and ts_subtree_release().

Referenced by ts_parser__reduce(), and ts_subtree_array_delete().

◆ ts_subtree_array_copy()

void ts_subtree_array_copy ( SubtreeArray  self,
SubtreeArray *  dest 
)

Definition at line 70 of file subtree.c.

70  {
71  dest->size = self.size;
72  dest->capacity = self.capacity;
73  dest->contents = self.contents;
74  if (self.capacity > 0) {
75  dest->contents = ts_calloc(self.capacity, sizeof(Subtree));
76  memcpy(dest->contents, self.contents, self.size * sizeof(Subtree));
77  for (uint32_t i = 0; i < self.size; i++) {
78  ts_subtree_retain(dest->contents[i]);
79  }
80  }
81 }
#define ts_calloc
Definition: alloc.h:24
char * dest
Definition: lz4.h:697
void ts_subtree_retain(Subtree self)
Definition: subtree.c:577

References dest, i, memcpy(), ts_calloc, and ts_subtree_retain().

Referenced by stack__iter().

◆ ts_subtree_array_delete()

void ts_subtree_array_delete ( SubtreePool pool,
SubtreeArray *  self 
)

Definition at line 90 of file subtree.c.

90  {
91  ts_subtree_array_clear(pool, self);
92  array_delete(self);
93 }
#define array_delete(self)
Definition: array.h:41
void ts_subtree_array_clear(SubtreePool *pool, SubtreeArray *self)
Definition: subtree.c:83

References array_delete, and ts_subtree_array_clear().

Referenced by stack__iter(), ts_parser__recover(), ts_parser__recover_to_state(), and ts_parser__reduce().

◆ ts_subtree_array_remove_trailing_extras()

void ts_subtree_array_remove_trailing_extras ( SubtreeArray *  self,
SubtreeArray *  destination 
)

Definition at line 95 of file subtree.c.

98  {
99  array_clear(destination);
100  while (self->size > 0) {
101  Subtree last = self->contents[self->size - 1];
102  if (ts_subtree_extra(last)) {
103  self->size--;
104  array_push(destination, last);
105  } else {
106  break;
107  }
108  }
109  ts_subtree_array_reverse(destination);
110 }
void ts_subtree_array_reverse(SubtreeArray *self)
Definition: subtree.c:112

References array_clear, array_push, ts_subtree_array_reverse(), and ts_subtree_extra().

Referenced by ts_parser__recover_to_state(), and ts_parser__reduce().

◆ ts_subtree_array_reverse()

void ts_subtree_array_reverse ( SubtreeArray *  self)

Definition at line 112 of file subtree.c.

112  {
113  for (uint32_t i = 0, limit = self->size / 2; i < limit; i++) {
114  size_t reverse_index = self->size - 1 - i;
115  Subtree swap = self->contents[i];
116  self->contents[i] = self->contents[reverse_index];
117  self->contents[reverse_index] = swap;
118  }
119 }
#define swap(a, b)
Definition: qsort.h:111

References i, limit, and swap.

Referenced by stack__iter(), and ts_subtree_array_remove_trailing_extras().

◆ ts_subtree_balance()

void ts_subtree_balance ( Subtree  self,
SubtreePool pool,
const TSLanguage language 
)

Definition at line 338 of file subtree.c.

338  {
339  array_clear(&pool->tree_stack);
340 
341  if (ts_subtree_child_count(self) > 0 && self.ptr->ref_count == 1) {
343  }
344 
345  while (pool->tree_stack.size > 0) {
346  MutableSubtree tree = array_pop(&pool->tree_stack);
347 
348  if (tree.ptr->repeat_depth > 0) {
349  Subtree child1 = ts_subtree_children(tree)[0];
350  Subtree child2 = ts_subtree_children(tree)[tree.ptr->child_count - 1];
351  long repeat_delta = (long)ts_subtree_repeat_depth(child1) - (long)ts_subtree_repeat_depth(child2);
352  if (repeat_delta > 0) {
353  unsigned n = repeat_delta;
354  for (unsigned i = n / 2; i > 0; i /= 2) {
355  ts_subtree__compress(tree, i, language, &pool->tree_stack);
356  n -= i;
357  }
358  }
359  }
360 
361  for (uint32_t i = 0; i < tree.ptr->child_count; i++) {
362  Subtree child = ts_subtree_children(tree)[i];
363  if (ts_subtree_child_count(child) > 0 && child.ptr->ref_count == 1) {
365  }
366  }
367  }
368 }
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 long
Definition: sflib.h:79
uint32_t repeat_depth
Definition: subtree.h:138
MutableSubtreeArray tree_stack
Definition: subtree.h:172
static void ts_subtree__compress(MutableSubtree self, unsigned count, const TSLanguage *language, MutableSubtreeArray *stack)
Definition: subtree.c:292

References array_clear, array_pop, array_push, SubtreeHeapData::child_count, i, long, n, Subtree::ptr, MutableSubtree::ptr, SubtreeHeapData::ref_count, SubtreeHeapData::repeat_depth, SubtreePool::tree_stack, ts_subtree__compress(), ts_subtree_child_count(), ts_subtree_children, ts_subtree_repeat_depth(), and ts_subtree_to_mut_unsafe().

Referenced by ts_parser_parse().

◆ ts_subtree_can_inline()

static bool ts_subtree_can_inline ( Length  padding,
Length  size,
uint32_t  lookahead_bytes 
)
inlinestatic

Definition at line 157 of file subtree.c.

157  {
158  return
159  padding.bytes < TS_MAX_INLINE_TREE_LENGTH &&
160  padding.extent.row < 16 &&
162  size.extent.row == 0 &&
163  size.extent.column < TS_MAX_INLINE_TREE_LENGTH &&
164  lookahead_bytes < 16;
165 }
voidpf void uLong size
Definition: ioapi.h:138
uint32_t bytes
Definition: length.h:10
TSPoint extent
Definition: length.h:11
uint32_t row
Definition: api.h:56
uint32_t column
Definition: api.h:57
#define TS_MAX_INLINE_TREE_LENGTH
Definition: subtree.c:21

References Length::bytes, TSPoint::column, Length::extent, TSPoint::row, and TS_MAX_INLINE_TREE_LENGTH.

Referenced by ts_subtree_edit(), and ts_subtree_new_leaf().

◆ ts_subtree_clone()

MutableSubtree ts_subtree_clone ( Subtree  self)

Definition at line 260 of file subtree.c.

260  {
261  size_t alloc_size = ts_subtree_alloc_size(self.ptr->child_count);
262  Subtree *new_children = ts_malloc(alloc_size);
263  Subtree *old_children = ts_subtree_children(self);
264  memcpy(new_children, old_children, alloc_size);
265  SubtreeHeapData *result = (SubtreeHeapData *)&new_children[self.ptr->child_count];
266  if (self.ptr->child_count > 0) {
267  for (uint32_t i = 0; i < self.ptr->child_count; i++) {
268  ts_subtree_retain(new_children[i]);
269  }
270  } else if (self.ptr->has_external_tokens) {
272  &self.ptr->external_scanner_state
273  );
274  }
275  result->ref_count = 1;
276  return (MutableSubtree) {.ptr = result};
277 }
ExternalScannerState external_scanner_state
Definition: subtree.h:148
ExternalScannerState ts_external_scanner_state_copy(const ExternalScannerState *self)
Definition: subtree.c:38
static size_t ts_subtree_alloc_size(uint32_t child_count)
Definition: subtree.h:227
if(dbg->bits==RZ_SYS_BITS_64)
Definition: windows-arm64.h:4

References SubtreeHeapData::external_scanner_state, i, if(), memcpy(), SubtreeHeapData::ref_count, ts_external_scanner_state_copy(), ts_malloc, ts_subtree_alloc_size(), ts_subtree_children, and ts_subtree_retain().

Referenced by ts_subtree_make_mut().

◆ ts_subtree_compare()

int ts_subtree_compare ( Subtree  left,
Subtree  right 
)

Definition at line 615 of file subtree.c.

615  {
616  if (ts_subtree_symbol(left) < ts_subtree_symbol(right)) return -1;
617  if (ts_subtree_symbol(right) < ts_subtree_symbol(left)) return 1;
618  if (ts_subtree_child_count(left) < ts_subtree_child_count(right)) return -1;
619  if (ts_subtree_child_count(right) < ts_subtree_child_count(left)) return 1;
620  for (uint32_t i = 0, n = ts_subtree_child_count(left); i < n; i++) {
621  Subtree left_child = ts_subtree_children(left)[i];
622  Subtree right_child = ts_subtree_children(right)[i];
623  switch (ts_subtree_compare(left_child, right_child)) {
624  case -1: return -1;
625  case 1: return 1;
626  default: break;
627  }
628  }
629  return 0;
630 }
int ts_subtree_compare(Subtree left, Subtree right)
Definition: subtree.c:615

References i, n, ts_subtree_child_count(), ts_subtree_children, and ts_subtree_symbol().

Referenced by ts_parser__select_tree().

◆ ts_subtree_edit()

Subtree ts_subtree_edit ( Subtree  self,
const TSInputEdit edit,
SubtreePool pool 
)

Definition at line 640 of file subtree.c.

640  {
641  typedef struct {
642  Subtree *tree;
643  Edit edit;
644  } StackEntry;
645 
648  .tree = &self,
649  .edit = (Edit) {
650  .start = {edit->start_byte, edit->start_point},
651  .old_end = {edit->old_end_byte, edit->old_end_point},
652  .new_end = {edit->new_end_byte, edit->new_end_point},
653  },
654  }));
655 
656  while (stack.size) {
658  Edit edit = entry.edit;
659  bool is_noop = edit.old_end.bytes == edit.start.bytes && edit.new_end.bytes == edit.start.bytes;
660  bool is_pure_insertion = edit.old_end.bytes == edit.start.bytes;
661  bool invalidate_first_row = ts_subtree_depends_on_column(*entry.tree);
662 
663  Length size = ts_subtree_size(*entry.tree);
664  Length padding = ts_subtree_padding(*entry.tree);
665  uint32_t lookahead_bytes = ts_subtree_lookahead_bytes(*entry.tree);
666  uint32_t end_byte = padding.bytes + size.bytes + lookahead_bytes;
667  if (edit.start.bytes > end_byte || (is_noop && edit.start.bytes == end_byte)) continue;
668 
669  // If the edit is entirely within the space before this subtree, then shift this
670  // subtree over according to the edit without changing its size.
671  if (edit.old_end.bytes <= padding.bytes) {
672  padding = length_add(edit.new_end, length_sub(padding, edit.old_end));
673  }
674 
675  // If the edit starts in the space before this subtree and extends into this subtree,
676  // shrink the subtree's content to compensate for the change in the space before it.
677  else if (edit.start.bytes < padding.bytes) {
678  size = length_sub(size, length_sub(edit.old_end, padding));
679  padding = edit.new_end;
680  }
681 
682  // If the edit is a pure insertion right at the start of the subtree,
683  // shift the subtree over according to the insertion.
684  else if (edit.start.bytes == padding.bytes && is_pure_insertion) {
685  padding = edit.new_end;
686  }
687 
688  // If the edit is within this subtree, resize the subtree to reflect the edit.
689  else {
690  uint32_t total_bytes = padding.bytes + size.bytes;
691  if (edit.start.bytes < total_bytes ||
692  (edit.start.bytes == total_bytes && is_pure_insertion)) {
693  size = length_add(
694  length_sub(edit.new_end, padding),
695  length_sub(size, length_sub(edit.old_end, padding))
696  );
697  }
698  }
699 
700  MutableSubtree result = ts_subtree_make_mut(pool, *entry.tree);
701 
702  if (result.data.is_inline) {
703  if (ts_subtree_can_inline(padding, size, lookahead_bytes)) {
704  result.data.padding_bytes = padding.bytes;
705  result.data.padding_rows = padding.extent.row;
706  result.data.padding_columns = padding.extent.column;
707  result.data.size_bytes = size.bytes;
708  } else {
710  data->ref_count = 1;
711  data->padding = padding;
712  data->size = size;
713  data->lookahead_bytes = lookahead_bytes;
714  data->error_cost = 0;
715  data->child_count = 0;
716  data->symbol = result.data.symbol;
717  data->parse_state = result.data.parse_state;
718  data->visible = result.data.visible;
719  data->named = result.data.named;
720  data->extra = result.data.extra;
721  data->fragile_left = false;
722  data->fragile_right = false;
723  data->has_changes = false;
724  data->has_external_tokens = false;
725  data->depends_on_column = false;
726  data->is_missing = result.data.is_missing;
727  data->is_keyword = result.data.is_keyword;
728  result.ptr = data;
729  }
730  } else {
731  result.ptr->padding = padding;
732  result.ptr->size = size;
733  }
734 
736  *entry.tree = ts_subtree_from_mut(result);
737 
738  Length child_left, child_right = length_zero();
739  for (uint32_t i = 0, n = ts_subtree_child_count(*entry.tree); i < n; i++) {
740  Subtree *child = &ts_subtree_children(*entry.tree)[i];
741  Length child_size = ts_subtree_total_size(*child);
742  child_left = child_right;
743  child_right = length_add(child_left, child_size);
744 
745  // If this child ends before the edit, it is not affected.
746  if (child_right.bytes + ts_subtree_lookahead_bytes(*child) < edit.start.bytes) continue;
747 
748  // Keep editing child nodes until a node is reached that starts after the edit.
749  // Also, if this node's validity depends on its column position, then continue
750  // invaliditing child nodes until reaching a line break.
751  if ((
752  (child_left.bytes > edit.old_end.bytes) ||
753  (child_left.bytes == edit.old_end.bytes && child_size.bytes > 0 && i > 0)
754  ) && (
755  !invalidate_first_row ||
756  child_left.extent.row > entry.tree->ptr->padding.extent.row
757  )) {
758  break;
759  }
760 
761  // Transform edit into the child's coordinate space.
762  Edit child_edit = {
763  .start = length_sub(edit.start, child_left),
764  .old_end = length_sub(edit.old_end, child_left),
765  .new_end = length_sub(edit.new_end, child_left),
766  };
767 
768  // Clamp child_edit to the child's bounds.
769  if (edit.start.bytes < child_left.bytes) child_edit.start = length_zero();
770  if (edit.old_end.bytes < child_left.bytes) child_edit.old_end = length_zero();
771  if (edit.new_end.bytes < child_left.bytes) child_edit.new_end = length_zero();
772  if (edit.old_end.bytes > child_right.bytes) child_edit.old_end = child_size;
773 
774  // Interpret all inserted text as applying to the *first* child that touches the edit.
775  // Subsequent children are only never have any text inserted into them; they are only
776  // shrunk to compensate for the edit.
777  if (
778  child_right.bytes > edit.start.bytes ||
779  (child_right.bytes == edit.start.bytes && is_pure_insertion)
780  ) {
781  edit.new_end = edit.start;
782  }
783 
784  // Children that occur before the edit are not reshaped by the edit.
785  else {
786  child_edit.old_end = child_edit.start;
787  child_edit.new_end = child_edit.start;
788  }
789 
790  // Queue processing of this child's subtree.
792  .tree = child,
793  .edit = child_edit,
794  }));
795  }
796  }
797 
799  return self;
800 }
#define array_new()
Definition: array.h:25
#define Array(T)
Definition: array.h:15
static Length length_zero(void)
Definition: length.h:39
static Length length_add(Length len1, Length len2)
Definition: length.h:25
static Length length_sub(Length len1, Length len2)
Definition: length.h:32
Definition: subtree.c:15
Length new_end
Definition: subtree.c:18
Length old_end
Definition: subtree.c:17
Length start
Definition: subtree.c:16
Definition: length.h:9
bool depends_on_column
Definition: subtree.h:128
bool fragile_right
Definition: subtree.h:125
bool fragile_left
Definition: subtree.h:124
bool is_keyword
Definition: subtree.h:130
bool has_changes
Definition: subtree.h:126
Length size
Definition: subtree.h:114
uint32_t lookahead_bytes
Definition: subtree.h:115
bool is_missing
Definition: subtree.h:129
TSStateId parse_state
Definition: subtree.h:119
Length padding
Definition: subtree.h:113
bool has_external_tokens
Definition: subtree.h:127
uint32_t error_cost
Definition: subtree.h:116
uint16_t parse_state
Definition: subtree.h:97
SUBTREE_BITS uint8_t symbol
Definition: subtree.h:96
uint32_t old_end_byte
Definition: api.h:85
uint32_t start_byte
Definition: api.h:84
uint32_t new_end_byte
Definition: api.h:86
TSPoint old_end_point
Definition: api.h:88
TSPoint start_point
Definition: api.h:87
TSPoint new_end_point
Definition: api.h:89
Definition: zipcmp.c:77
static void ts_subtree_set_has_changes(MutableSubtree *self)
Definition: subtree.c:632
static SubtreeHeapData * ts_subtree_pool_allocate(SubtreePool *self)
Definition: subtree.c:139
MutableSubtree ts_subtree_make_mut(SubtreePool *pool, Subtree self)
Definition: subtree.c:284
static bool ts_subtree_can_inline(Length padding, Length size, uint32_t lookahead_bytes)
Definition: subtree.c:157
static Length ts_subtree_total_size(Subtree self)
Definition: subtree.h:274
static Length ts_subtree_size(Subtree self)
Definition: subtree.h:265
static Length ts_subtree_padding(Subtree self)
Definition: subtree.h:256

References Array, array_delete, array_new, array_pop, array_push, Length::bytes, SubtreeHeapData::child_count, TSPoint::column, MutableSubtree::data, SubtreeHeapData::depends_on_column, SubtreeHeapData::error_cost, Length::extent, SubtreeHeapData::extra, SubtreeHeapData::fragile_left, SubtreeHeapData::fragile_right, SubtreeHeapData::has_changes, SubtreeHeapData::has_external_tokens, i, SubtreeInlineData::is_inline, SubtreeHeapData::is_keyword, SubtreeHeapData::is_missing, length_add(), length_sub(), length_zero(), SubtreeHeapData::lookahead_bytes, n, SubtreeHeapData::named, Edit::new_end, TSInputEdit::new_end_byte, TSInputEdit::new_end_point, Edit::old_end, TSInputEdit::old_end_byte, TSInputEdit::old_end_point, SubtreeHeapData::padding, SubtreeInlineData::parse_state, SubtreeHeapData::parse_state, MutableSubtree::ptr, SubtreeHeapData::ref_count, TSPoint::row, SubtreeHeapData::size, Edit::start, TSInputEdit::start_byte, TSInputEdit::start_point, SubtreeInlineData::symbol, SubtreeHeapData::symbol, ts_subtree_can_inline(), ts_subtree_child_count(), ts_subtree_children, ts_subtree_depends_on_column(), ts_subtree_from_mut(), ts_subtree_lookahead_bytes(), ts_subtree_make_mut(), ts_subtree_padding(), ts_subtree_pool_allocate(), ts_subtree_set_has_changes(), ts_subtree_size(), ts_subtree_total_size(), and SubtreeHeapData::visible.

Referenced by ts_tree_edit().

◆ ts_subtree_external_scanner_state_eq()

bool ts_subtree_external_scanner_state_eq ( Subtree  self,
Subtree  other 
)

Definition at line 1027 of file subtree.c.

1027  {
1028  const ExternalScannerState *state1 = &empty_state;
1029  const ExternalScannerState *state2 = &empty_state;
1030  if (self.ptr && ts_subtree_has_external_tokens(self) && !self.ptr->child_count) {
1031  state1 = &self.ptr->external_scanner_state;
1032  }
1033  if (other.ptr && ts_subtree_has_external_tokens(other) && !other.ptr->child_count) {
1034  state2 = &other.ptr->external_scanner_state;
1035  }
1036  return ts_external_scanner_state_eq(state1, state2);
1037 }
static const ExternalScannerState empty_state
Definition: subtree.c:24
bool ts_external_scanner_state_eq(const ExternalScannerState *a, const ExternalScannerState *b)
Definition: subtree.c:61
static bool ts_subtree_has_external_tokens(Subtree self)
Definition: subtree.h:330

References SubtreeHeapData::child_count, empty_state, SubtreeHeapData::external_scanner_state, Subtree::ptr, ts_external_scanner_state_eq(), and ts_subtree_has_external_tokens().

Referenced by stack__subtree_is_equivalent(), ts_parser__get_cached_token(), ts_parser__reuse_node(), and ts_stack_can_merge().

◆ ts_subtree_last_external_token()

Subtree ts_subtree_last_external_token ( Subtree  tree)

Definition at line 802 of file subtree.c.

802  {
803  if (!ts_subtree_has_external_tokens(tree)) return NULL_SUBTREE;
804  while (tree.ptr->child_count > 0) {
805  for (uint32_t i = tree.ptr->child_count - 1; i + 1 > 0; i--) {
806  Subtree child = ts_subtree_children(tree)[i];
807  if (ts_subtree_has_external_tokens(child)) {
808  tree = child;
809  break;
810  }
811  }
812  }
813  return tree;
814 }
#define NULL_SUBTREE
Definition: subtree.h:19

References SubtreeHeapData::child_count, i, NULL_SUBTREE, Subtree::ptr, ts_subtree_children, and ts_subtree_has_external_tokens().

Referenced by reusable_node_advance(), ts_parser__recover(), and ts_parser__shift().

◆ ts_subtree_make_mut()

MutableSubtree ts_subtree_make_mut ( SubtreePool pool,
Subtree  self 
)

Definition at line 284 of file subtree.c.

284  {
285  if (self.data.is_inline) return (MutableSubtree) {self.data};
286  if (self.ptr->ref_count == 1) return ts_subtree_to_mut_unsafe(self);
287  MutableSubtree result = ts_subtree_clone(self);
288  ts_subtree_release(pool, self);
289  return result;
290 }
MutableSubtree ts_subtree_clone(Subtree self)
Definition: subtree.c:260

References MutableSubtree::data, ts_subtree_clone(), ts_subtree_release(), and ts_subtree_to_mut_unsafe().

Referenced by ts_parser__advance(), ts_parser__recover(), ts_parser__shift(), and ts_subtree_edit().

◆ ts_subtree_new_error()

Subtree ts_subtree_new_error ( SubtreePool pool,
int32_t  lookahead_char,
Length  padding,
Length  size,
uint32_t  bytes_scanned,
TSStateId  parse_state,
const TSLanguage language 
)

Definition at line 244 of file subtree.c.

247  {
248  Subtree result = ts_subtree_new_leaf(
249  pool, ts_builtin_sym_error, padding, size, bytes_scanned,
250  parse_state, false, false, false, language
251  );
252  SubtreeHeapData *data = (SubtreeHeapData *)result.ptr;
253  data->fragile_left = true;
254  data->fragile_right = true;
255  data->lookahead_char = lookahead_char;
256  return result;
257 }
#define ts_builtin_sym_error
Definition: parser.h:12
Subtree ts_subtree_new_leaf(SubtreePool *pool, TSSymbol symbol, Length padding, Length size, uint32_t lookahead_bytes, TSStateId parse_state, bool has_external_tokens, bool depends_on_column, bool is_keyword, const TSLanguage *language)
Definition: subtree.c:167

References SubtreeHeapData::fragile_left, SubtreeHeapData::fragile_right, SubtreeHeapData::lookahead_char, Subtree::ptr, ts_builtin_sym_error, and ts_subtree_new_leaf().

Referenced by ts_parser__lex().

◆ ts_subtree_new_error_node()

Subtree ts_subtree_new_error_node ( SubtreeArray *  children,
bool  extra,
const TSLanguage language 
)

Definition at line 542 of file subtree.c.

546  {
548  ts_builtin_sym_error, children, 0, language
549  );
550  result.ptr->extra = extra;
551  return ts_subtree_from_mut(result);
552 }
MutableSubtree ts_subtree_new_node(TSSymbol symbol, SubtreeArray *children, unsigned production_id, const TSLanguage *language)
Definition: subtree.c:500

References SubtreeHeapData::extra, MutableSubtree::ptr, ts_builtin_sym_error, ts_subtree_from_mut(), and ts_subtree_new_node().

Referenced by ts_parser__recover(), and ts_parser__recover_to_state().

◆ ts_subtree_new_leaf()

Subtree ts_subtree_new_leaf ( SubtreePool pool,
TSSymbol  symbol,
Length  padding,
Length  size,
uint32_t  lookahead_bytes,
TSStateId  parse_state,
bool  has_external_tokens,
bool  depends_on_column,
bool  is_keyword,
const TSLanguage language 
)

Definition at line 167 of file subtree.c.

172  {
173  TSSymbolMetadata metadata = ts_language_symbol_metadata(language, symbol);
174  bool extra = symbol == ts_builtin_sym_end;
175 
176  bool is_inline = (
177  symbol <= UINT8_MAX &&
178  !has_external_tokens &&
179  ts_subtree_can_inline(padding, size, lookahead_bytes)
180  );
181 
182  if (is_inline) {
183  return (Subtree) {{
184  .parse_state = parse_state,
185  .symbol = symbol,
186  .padding_bytes = padding.bytes,
187  .padding_rows = padding.extent.row,
188  .padding_columns = padding.extent.column,
189  .size_bytes = size.bytes,
190  .lookahead_bytes = lookahead_bytes,
191  .visible = metadata.visible,
192  .named = metadata.named,
193  .extra = extra,
194  .has_changes = false,
195  .is_missing = false,
196  .is_keyword = is_keyword,
197  .is_inline = true,
198  }};
199  } else {
201  *data = (SubtreeHeapData) {
202  .ref_count = 1,
203  .padding = padding,
204  .size = size,
205  .lookahead_bytes = lookahead_bytes,
206  .error_cost = 0,
207  .child_count = 0,
208  .symbol = symbol,
209  .parse_state = parse_state,
210  .visible = metadata.visible,
211  .named = metadata.named,
212  .extra = extra,
213  .fragile_left = false,
214  .fragile_right = false,
215  .has_changes = false,
216  .has_external_tokens = has_external_tokens,
217  .depends_on_column = depends_on_column,
218  .is_missing = false,
219  .is_keyword = is_keyword,
220  {{.first_leaf = {.symbol = 0, .parse_state = 0}}}
221  };
222  return (Subtree) {.ptr = data};
223  }
224 }
#define ts_builtin_sym_end
Definition: parser.h:13
#define UINT8_MAX
bool visible
Definition: parser.h:36

References Length::bytes, TSPoint::column, Length::extent, TSSymbolMetadata::named, SubtreeHeapData::ref_count, TSPoint::row, ts_builtin_sym_end, ts_language_symbol_metadata(), ts_subtree_can_inline(), ts_subtree_pool_allocate(), UINT8_MAX, and TSSymbolMetadata::visible.

Referenced by ts_parser__lex(), ts_subtree_new_error(), and ts_subtree_new_missing_leaf().

◆ ts_subtree_new_missing_leaf()

Subtree ts_subtree_new_missing_leaf ( SubtreePool pool,
TSSymbol  symbol,
Length  padding,
uint32_t  lookahead_bytes,
const TSLanguage language 
)

Definition at line 558 of file subtree.c.

564  {
565  Subtree result = ts_subtree_new_leaf(
566  pool, symbol, padding, length_zero(), lookahead_bytes,
567  0, false, false, false, language
568  );
569  if (result.data.is_inline) {
570  result.data.is_missing = true;
571  } else {
572  ((SubtreeHeapData *)result.ptr)->is_missing = true;
573  }
574  return result;
575 }
SubtreeInlineData data
Definition: subtree.h:157

References Subtree::data, SubtreeInlineData::is_inline, length_zero(), Subtree::ptr, and ts_subtree_new_leaf().

Referenced by ts_parser__handle_error().

◆ ts_subtree_new_node()

MutableSubtree ts_subtree_new_node ( TSSymbol  symbol,
SubtreeArray *  children,
unsigned  production_id,
const TSLanguage language 
)

Definition at line 500 of file subtree.c.

505  {
506  TSSymbolMetadata metadata = ts_language_symbol_metadata(language, symbol);
507  bool fragile = symbol == ts_builtin_sym_error || symbol == ts_builtin_sym_error_repeat;
508 
509  // Allocate the node's data at the end of the array of children.
510  size_t new_byte_size = ts_subtree_alloc_size(children->size);
511  if (children->capacity * sizeof(Subtree) < new_byte_size) {
512  children->contents = ts_realloc(children->contents, new_byte_size);
513  children->capacity = new_byte_size / sizeof(Subtree);
514  }
515  SubtreeHeapData *data = (SubtreeHeapData *)&children->contents[children->size];
516 
517  *data = (SubtreeHeapData) {
518  .ref_count = 1,
519  .symbol = symbol,
520  .child_count = children->size,
521  .visible = metadata.visible,
522  .named = metadata.named,
523  .has_changes = false,
524  .fragile_left = fragile,
525  .fragile_right = fragile,
526  .is_keyword = false,
527  {{
528  .node_count = 0,
529  .production_id = production_id,
530  .first_leaf = {.symbol = 0, .parse_state = 0},
531  }}
532  };
533  MutableSubtree result = {.ptr = data};
534  ts_subtree_summarize_children(result, language);
535  return result;
536 }
#define ts_realloc
Definition: alloc.h:27
#define ts_builtin_sym_error_repeat
Definition: language.h:11

References TSSymbolMetadata::named, MutableSubtree::ptr, SubtreeHeapData::ref_count, ts_builtin_sym_error, ts_builtin_sym_error_repeat, ts_language_symbol_metadata(), ts_realloc, ts_subtree_alloc_size(), ts_subtree_summarize_children(), and TSSymbolMetadata::visible.

Referenced by ts_parser__accept(), ts_parser__recover(), ts_parser__reduce(), ts_parser__select_children(), and ts_subtree_new_error_node().

◆ ts_subtree_pool_allocate()

static SubtreeHeapData* ts_subtree_pool_allocate ( SubtreePool self)
static

Definition at line 139 of file subtree.c.

139  {
140  if (self->free_trees.size > 0) {
141  return array_pop(&self->free_trees).ptr;
142  } else {
143  return ts_malloc(sizeof(SubtreeHeapData));
144  }
145 }
MutableSubtreeArray free_trees
Definition: subtree.h:171

References array_pop, and ts_malloc.

Referenced by ts_subtree_edit(), and ts_subtree_new_leaf().

◆ ts_subtree_pool_delete()

void ts_subtree_pool_delete ( SubtreePool self)

Definition at line 129 of file subtree.c.

129  {
130  if (self->free_trees.contents) {
131  for (unsigned i = 0; i < self->free_trees.size; i++) {
132  ts_free(self->free_trees.contents[i].ptr);
133  }
134  array_delete(&self->free_trees);
135  }
136  if (self->tree_stack.contents) array_delete(&self->tree_stack);
137 }

References array_delete, i, and ts_free.

Referenced by ts_parser_delete(), ts_tree_delete(), and ts_tree_edit().

◆ ts_subtree_pool_free()

static void ts_subtree_pool_free ( SubtreePool self,
SubtreeHeapData tree 
)
static

Definition at line 147 of file subtree.c.

147  {
148  if (self->free_trees.capacity > 0 && self->free_trees.size + 1 <= TS_MAX_TREE_POOL_SIZE) {
149  array_push(&self->free_trees, (MutableSubtree) {.ptr = tree});
150  } else {
151  ts_free(tree);
152  }
153 }
#define TS_MAX_TREE_POOL_SIZE
Definition: subtree.c:22

References array_push, ts_free, and TS_MAX_TREE_POOL_SIZE.

Referenced by ts_subtree_release().

◆ ts_subtree_pool_new()

SubtreePool ts_subtree_pool_new ( uint32_t  capacity)

Definition at line 123 of file subtree.c.

123  {
124  SubtreePool self = {array_new(), array_new()};
125  array_reserve(&self.free_trees, capacity);
126  return self;
127 }
#define array_reserve(self, new_capacity)
Definition: array.h:37

References array_new, and array_reserve.

Referenced by ts_parser_new(), ts_tree_delete(), and ts_tree_edit().

◆ ts_subtree_print_dot_graph()

void ts_subtree_print_dot_graph ( Subtree  self,
const TSLanguage language,
FILE *  f 
)

Definition at line 1020 of file subtree.c.

1020  {
1021  fprintf(f, "digraph tree {\n");
1022  fprintf(f, "edge [arrowhead=none]\n");
1023  ts_subtree__print_dot_graph(&self, 0, language, 0, f);
1024  fprintf(f, "}\n");
1025 }

References f, and ts_subtree__print_dot_graph().

Referenced by ts_tree_print_dot_graph().

◆ ts_subtree_release()

void ts_subtree_release ( SubtreePool pool,
Subtree  self 
)

Definition at line 584 of file subtree.c.

584  {
585  if (self.data.is_inline) return;
586  array_clear(&pool->tree_stack);
587 
588  assert(self.ptr->ref_count > 0);
589  if (atomic_dec((volatile uint32_t *)&self.ptr->ref_count) == 0) {
591  }
592 
593  while (pool->tree_stack.size > 0) {
594  MutableSubtree tree = array_pop(&pool->tree_stack);
595  if (tree.ptr->child_count > 0) {
596  Subtree *children = ts_subtree_children(tree);
597  for (uint32_t i = 0; i < tree.ptr->child_count; i++) {
598  Subtree child = children[i];
599  if (child.data.is_inline) continue;
600  assert(child.ptr->ref_count > 0);
601  if (atomic_dec((volatile uint32_t *)&child.ptr->ref_count) == 0) {
603  }
604  }
605  ts_free(children);
606  } else {
607  if (tree.ptr->has_external_tokens) {
609  }
610  ts_subtree_pool_free(pool, tree.ptr);
611  }
612  }
613 }
assert(limit<=UINT32_MAX/2)
static void ts_subtree_pool_free(SubtreePool *self, SubtreeHeapData *tree)
Definition: subtree.c:147
void ts_external_scanner_state_delete(ExternalScannerState *self)
Definition: subtree.c:47
static uint32_t atomic_dec(volatile uint32_t *p)
Definition: atomic.h:52

References array_clear, array_pop, array_push, assert(), atomic_dec(), SubtreeHeapData::child_count, Subtree::data, SubtreeHeapData::external_scanner_state, SubtreeHeapData::has_external_tokens, i, SubtreeInlineData::is_inline, Subtree::ptr, MutableSubtree::ptr, SubtreeHeapData::ref_count, SubtreePool::tree_stack, ts_external_scanner_state_delete(), ts_free, ts_subtree_children, ts_subtree_pool_free(), and ts_subtree_to_mut_unsafe().

Referenced by stack_head_delete(), stack_node_add_link(), stack_node_release(), ts_parser__accept(), ts_parser__advance(), ts_parser__breakdown_lookahead(), ts_parser__breakdown_top_of_stack(), ts_parser__recover(), ts_parser__reduce(), ts_parser__set_cached_token(), ts_parser_delete(), ts_parser_reset(), ts_stack_set_last_external_token(), ts_subtree_array_clear(), ts_subtree_make_mut(), and ts_tree_delete().

◆ ts_subtree_retain()

void ts_subtree_retain ( Subtree  self)

Definition at line 577 of file subtree.c.

577  {
578  if (self.data.is_inline) return;
579  assert(self.ptr->ref_count > 0);
580  atomic_inc((volatile uint32_t *)&self.ptr->ref_count);
581  assert(self.ptr->ref_count != 0);
582 }
static uint32_t atomic_inc(volatile uint32_t *p)
Definition: atomic.h:48

References assert(), and atomic_inc().

Referenced by stack__iter(), stack_node_add_link(), ts_parser__accept(), ts_parser__breakdown_lookahead(), ts_parser__breakdown_top_of_stack(), ts_parser__get_cached_token(), ts_parser__recover_to_state(), ts_parser__reuse_node(), ts_parser__set_cached_token(), ts_parser_parse(), ts_stack__add_version(), ts_stack_copy_version(), ts_stack_set_last_external_token(), ts_subtree_array_copy(), ts_subtree_clone(), and ts_tree_copy().

◆ ts_subtree_set_has_changes()

static void ts_subtree_set_has_changes ( MutableSubtree self)
inlinestatic

Definition at line 632 of file subtree.c.

632  {
633  if (self->data.is_inline) {
634  self->data.has_changes = true;
635  } else {
636  self->ptr->has_changes = true;
637  }
638 }

Referenced by ts_subtree_edit().

◆ ts_subtree_set_symbol()

void ts_subtree_set_symbol ( MutableSubtree self,
TSSymbol  symbol,
const TSLanguage language 
)

Definition at line 226 of file subtree.c.

230  {
231  TSSymbolMetadata metadata = ts_language_symbol_metadata(language, symbol);
232  if (self->data.is_inline) {
233  assert(symbol < UINT8_MAX);
234  self->data.symbol = symbol;
235  self->data.named = metadata.named;
236  self->data.visible = metadata.visible;
237  } else {
238  self->ptr->symbol = symbol;
239  self->ptr->named = metadata.named;
240  self->ptr->visible = metadata.visible;
241  }
242 }

References assert(), TSSymbolMetadata::named, ts_language_symbol_metadata(), UINT8_MAX, and TSSymbolMetadata::visible.

Referenced by ts_parser__advance().

◆ ts_subtree_string()

char* ts_subtree_string ( Subtree  self,
const TSLanguage language,
bool  include_all 
)

Definition at line 947 of file subtree.c.

951  {
952  char scratch_string[1];
954  self, scratch_string, 1,
955  language, include_all,
956  0, false, ROOT_FIELD
957  ) + 1;
958  char *result = ts_malloc(size * sizeof(char));
960  self, result, size,
961  language, include_all,
962  0, false, ROOT_FIELD
963  );
964  return result;
965 }

References ROOT_FIELD, ts_malloc, and ts_subtree__write_to_string().

Referenced by ts_node_string().

◆ ts_subtree_summarize_children()

void ts_subtree_summarize_children ( MutableSubtree  self,
const TSLanguage language 
)

Definition at line 371 of file subtree.c.

374  {
375  assert(!self.data.is_inline);
376 
377  self.ptr->named_child_count = 0;
378  self.ptr->visible_child_count = 0;
379  self.ptr->error_cost = 0;
380  self.ptr->repeat_depth = 0;
381  self.ptr->node_count = 1;
382  self.ptr->has_external_tokens = false;
383  self.ptr->depends_on_column = false;
384  self.ptr->dynamic_precedence = 0;
385 
386  uint32_t structural_index = 0;
387  const TSSymbol *alias_sequence = ts_language_alias_sequence(language, self.ptr->production_id);
388  uint32_t lookahead_end_byte = 0;
389 
390  const Subtree *children = ts_subtree_children(self);
391  for (uint32_t i = 0; i < self.ptr->child_count; i++) {
392  Subtree child = children[i];
393 
394  if (
395  self.ptr->size.extent.row == 0 &&
397  ) {
398  self.ptr->depends_on_column = true;
399  }
400 
401  if (i == 0) {
402  self.ptr->padding = ts_subtree_padding(child);
403  self.ptr->size = ts_subtree_size(child);
404  } else {
405  self.ptr->size = length_add(self.ptr->size, ts_subtree_total_size(child));
406  }
407 
408  uint32_t child_lookahead_end_byte =
409  self.ptr->padding.bytes +
410  self.ptr->size.bytes +
412  if (child_lookahead_end_byte > lookahead_end_byte) {
413  lookahead_end_byte = child_lookahead_end_byte;
414  }
415 
417  self.ptr->error_cost += ts_subtree_error_cost(child);
418  }
419 
420  uint32_t grandchild_count = ts_subtree_child_count(child);
421  if (
422  self.ptr->symbol == ts_builtin_sym_error ||
423  self.ptr->symbol == ts_builtin_sym_error_repeat
424  ) {
425  if (!ts_subtree_extra(child) && !(ts_subtree_is_error(child) && grandchild_count == 0)) {
426  if (ts_subtree_visible(child)) {
427  self.ptr->error_cost += ERROR_COST_PER_SKIPPED_TREE;
428  } else if (grandchild_count > 0) {
429  self.ptr->error_cost += ERROR_COST_PER_SKIPPED_TREE * child.ptr->visible_child_count;
430  }
431  }
432  }
433 
434  self.ptr->dynamic_precedence += ts_subtree_dynamic_precedence(child);
435  self.ptr->node_count += ts_subtree_node_count(child);
436 
437  if (alias_sequence && alias_sequence[structural_index] != 0 && !ts_subtree_extra(child)) {
438  self.ptr->visible_child_count++;
439  if (ts_language_symbol_metadata(language, alias_sequence[structural_index]).named) {
440  self.ptr->named_child_count++;
441  }
442  } else if (ts_subtree_visible(child)) {
443  self.ptr->visible_child_count++;
444  if (ts_subtree_named(child)) self.ptr->named_child_count++;
445  } else if (grandchild_count > 0) {
446  self.ptr->visible_child_count += child.ptr->visible_child_count;
447  self.ptr->named_child_count += child.ptr->named_child_count;
448  }
449 
450  if (ts_subtree_has_external_tokens(child)) self.ptr->has_external_tokens = true;
451 
452  if (ts_subtree_is_error(child)) {
453  self.ptr->fragile_left = self.ptr->fragile_right = true;
454  self.ptr->parse_state = TS_TREE_STATE_NONE;
455  }
456 
457  if (!ts_subtree_extra(child)) structural_index++;
458  }
459 
460  self.ptr->lookahead_bytes = lookahead_end_byte - self.ptr->size.bytes - self.ptr->padding.bytes;
461 
462  if (
463  self.ptr->symbol == ts_builtin_sym_error ||
464  self.ptr->symbol == ts_builtin_sym_error_repeat
465  ) {
466  self.ptr->error_cost +=
468  ERROR_COST_PER_SKIPPED_CHAR * self.ptr->size.bytes +
469  ERROR_COST_PER_SKIPPED_LINE * self.ptr->size.extent.row;
470  }
471 
472  if (self.ptr->child_count > 0) {
473  Subtree first_child = children[0];
474  Subtree last_child = children[self.ptr->child_count - 1];
475 
476  self.ptr->first_leaf.symbol = ts_subtree_leaf_symbol(first_child);
477  self.ptr->first_leaf.parse_state = ts_subtree_leaf_parse_state(first_child);
478 
479  if (ts_subtree_fragile_left(first_child)) self.ptr->fragile_left = true;
480  if (ts_subtree_fragile_right(last_child)) self.ptr->fragile_right = true;
481 
482  if (
483  self.ptr->child_count >= 2 &&
484  !self.ptr->visible &&
485  !self.ptr->named &&
486  ts_subtree_symbol(first_child) == self.ptr->symbol
487  ) {
488  if (ts_subtree_repeat_depth(first_child) > ts_subtree_repeat_depth(last_child)) {
489  self.ptr->repeat_depth = ts_subtree_repeat_depth(first_child) + 1;
490  } else {
491  self.ptr->repeat_depth = ts_subtree_repeat_depth(last_child) + 1;
492  }
493  }
494  }
495 }
#define ERROR_COST_PER_SKIPPED_TREE
Definition: error_costs.h:7
#define ERROR_COST_PER_SKIPPED_LINE
Definition: error_costs.h:8
#define ERROR_COST_PER_RECOVERY
Definition: error_costs.h:5
#define ERROR_COST_PER_SKIPPED_CHAR
Definition: error_costs.h:9
uint32_t visible_child_count
Definition: subtree.h:135
uint32_t named_child_count
Definition: subtree.h:136
struct SubtreeHeapData::@621::@623::@625 first_leaf
static bool ts_subtree_fragile_left(Subtree self)
Definition: subtree.h:322
#define TS_TREE_STATE_NONE
Definition: subtree.h:18
static int32_t ts_subtree_dynamic_precedence(Subtree self)
Definition: subtree.h:310
static TSSymbol ts_subtree_leaf_symbol(Subtree self)
Definition: subtree.h:244
static TSStateId ts_subtree_leaf_parse_state(Subtree self)
Definition: subtree.h:250
static uint32_t ts_subtree_node_count(Subtree self)
Definition: subtree.h:290
static bool ts_subtree_fragile_right(Subtree self)
Definition: subtree.h:326

References assert(), SubtreeHeapData::depends_on_column, ERROR_COST_PER_RECOVERY, ERROR_COST_PER_SKIPPED_CHAR, ERROR_COST_PER_SKIPPED_LINE, ERROR_COST_PER_SKIPPED_TREE, SubtreeHeapData::first_leaf, i, length_add(), SubtreeHeapData::named_child_count, Subtree::ptr, ts_builtin_sym_error, ts_builtin_sym_error_repeat, ts_language_alias_sequence(), ts_language_symbol_metadata(), ts_subtree_child_count(), ts_subtree_children, ts_subtree_depends_on_column(), ts_subtree_dynamic_precedence(), ts_subtree_error_cost(), ts_subtree_extra(), ts_subtree_fragile_left(), ts_subtree_fragile_right(), ts_subtree_has_external_tokens(), ts_subtree_is_error(), ts_subtree_leaf_parse_state(), ts_subtree_leaf_symbol(), ts_subtree_lookahead_bytes(), ts_subtree_named(), ts_subtree_node_count(), ts_subtree_padding(), ts_subtree_repeat_depth(), ts_subtree_size(), ts_subtree_symbol(), ts_subtree_total_size(), ts_subtree_visible(), TS_TREE_STATE_NONE, and SubtreeHeapData::visible_child_count.

Referenced by ts_subtree__compress(), and ts_subtree_new_node().

Variable Documentation

◆ empty_state

const ExternalScannerState empty_state = {{.short_data = {0}}, .length = 0}
static

Definition at line 24 of file subtree.c.

Referenced by ts_subtree_external_scanner_state_eq().

◆ ROOT_FIELD

const char* ROOT_FIELD = "__ROOT__"
static

Definition at line 845 of file subtree.c.

Referenced by ts_subtree__write_to_string(), and ts_subtree_string().