Use 2-space indent in c files

This commit is contained in:
Max Brunsfeld 2014-07-20 20:27:33 -07:00
parent af5a118000
commit df359bc01f
10 changed files with 614 additions and 611 deletions

View file

@ -13,15 +13,15 @@ typedef struct TSTree TSTree;
#define ts_lex_state_error 0
typedef struct {
TSInput input;
int debug;
const char *chunk;
size_t chunk_start;
size_t chunk_size;
size_t position_in_chunk;
size_t token_end_position;
size_t token_start_position;
int reached_end;
TSInput input;
int debug;
const char *chunk;
size_t chunk_start;
size_t chunk_size;
size_t position_in_chunk;
size_t token_end_position;
size_t token_start_position;
int reached_end;
} TSLexer;
TSLexer ts_lexer_make();
@ -29,26 +29,26 @@ int ts_lexer_advance(TSLexer *lexer);
TSTree * ts_lexer_build_node(TSLexer *lexer, TSSymbol symbol, int is_hidden);
static inline size_t ts_lexer_position(const TSLexer *lexer) {
return lexer->chunk_start + lexer->position_in_chunk;
return lexer->chunk_start + lexer->position_in_chunk;
}
static inline char ts_lexer_lookahead_char(const TSLexer *lexer) {
return lexer->chunk[lexer->position_in_chunk];
return lexer->chunk[lexer->position_in_chunk];
}
static inline void ts_lexer_start_token(TSLexer *lexer) {
lexer->token_start_position = ts_lexer_position(lexer);
lexer->token_start_position = ts_lexer_position(lexer);
}
typedef unsigned short TSStateId;
typedef struct {
size_t size;
struct {
TSTree *node;
TSStateId state;
int is_extra;
} *entries;
size_t size;
struct {
TSTree *node;
TSStateId state;
int is_extra;
} *entries;
} TSStack;
TSStack ts_stack_make();
@ -61,41 +61,41 @@ TSTree * ts_stack_top_node(const TSStack *stack);
size_t ts_stack_right_position(const TSStack *stack);
typedef enum {
TSParseActionTypeError,
TSParseActionTypeShift,
TSParseActionTypeShiftExtra,
TSParseActionTypeReduce,
TSParseActionTypeReduceExtra,
TSParseActionTypeAccept,
TSParseActionTypeError,
TSParseActionTypeShift,
TSParseActionTypeShiftExtra,
TSParseActionTypeReduce,
TSParseActionTypeReduceExtra,
TSParseActionTypeAccept,
} TSParseActionType;
typedef struct {
TSParseActionType type;
union {
TSStateId to_state;
struct {
TSSymbol symbol;
unsigned short child_count;
};
} data;
TSParseActionType type;
union {
TSStateId to_state;
struct {
TSSymbol symbol;
unsigned short child_count;
};
} data;
} TSParseAction;
typedef struct {
size_t symbol_count;
const char **symbol_names;
const int *hidden_symbol_flags;
const TSParseAction *parse_table;
const TSStateId *lex_states;
TSTree * (* lex_fn)(TSParser *, TSStateId);
size_t symbol_count;
const char **symbol_names;
const int *hidden_symbol_flags;
const TSParseAction *parse_table;
const TSStateId *lex_states;
TSTree * (* lex_fn)(TSParser *, TSStateId);
} TSParserConfig;
struct TSParser {
TSLexer lexer;
TSStack stack;
int debug;
TSTree *lookahead;
TSTree *next_lookahead;
TSParserConfig config;
TSLexer lexer;
TSStack stack;
int debug;
TSTree *lookahead;
TSTree *next_lookahead;
TSParserConfig config;
};
TSParser * ts_parser_make(TSParserConfig);
@ -106,84 +106,84 @@ void ts_parser_start(TSParser *parser, TSInput input, TSInputEdit *edit);
TSTree * ts_parser_step(TSParser *parser);
#define SYMBOL_NAMES \
static const char *ts_symbol_names[]
static const char *ts_symbol_names[]
#define HIDDEN_SYMBOLS \
static const int ts_hidden_symbol_flags[SYMBOL_COUNT]
static const int ts_hidden_symbol_flags[SYMBOL_COUNT]
#define LEX_STATES \
static TSStateId ts_lex_states[STATE_COUNT]
static TSStateId ts_lex_states[STATE_COUNT]
#define PARSE_TABLE \
static const TSParseAction ts_parse_actions[STATE_COUNT][SYMBOL_COUNT]
static const TSParseAction ts_parse_actions[STATE_COUNT][SYMBOL_COUNT]
#define LEX_FN() \
static TSTree * ts_lex(TSParser *parser, TSStateId lex_state)
static TSTree * ts_lex(TSParser *parser, TSStateId lex_state)
#define DEBUG_LEX(...) \
if (parser->lexer.debug) { fprintf(stderr, "\n" __VA_ARGS__); }
if (parser->lexer.debug) { fprintf(stderr, "\n" __VA_ARGS__); }
#define START_LEXER() \
DEBUG_LEX("LEX %d", lex_state); \
char lookahead; \
next_state: \
lookahead = ts_lexer_lookahead_char(&parser->lexer); \
DEBUG_LEX("CHAR '%c'", lookahead);
DEBUG_LEX("LEX %d", lex_state); \
char lookahead; \
next_state: \
lookahead = ts_lexer_lookahead_char(&parser->lexer); \
DEBUG_LEX("CHAR '%c'", lookahead);
#define START_TOKEN() \
ts_lexer_start_token(&parser->lexer);
ts_lexer_start_token(&parser->lexer);
#define ADVANCE(state_index) \
{ \
{ \
DEBUG_LEX("ADVANCE %d", state_index); \
if (!ts_lexer_advance(&parser->lexer)) ACCEPT_TOKEN(ts_builtin_sym_end); \
lex_state = state_index; goto next_state; \
}
}
#define ACCEPT_TOKEN(symbol) \
{ \
{ \
DEBUG_LEX("TOKEN %s", ts_symbol_names[symbol]); \
return ts_lexer_build_node(&parser->lexer, symbol, ts_hidden_symbol_flags[symbol]); \
}
}
#define LEX_ERROR() \
{ \
{ \
DEBUG_LEX("ERROR"); \
return ts_lexer_build_node(&parser->lexer, ts_builtin_sym_error, 0); \
}
}
#define LEX_PANIC() \
{ \
{ \
DEBUG_LEX("LEX ERROR: unexpected state %d", lex_state); \
return NULL; \
}
}
#define SHIFT(to_state_value) \
{ .type = TSParseActionTypeShift, .data = { .to_state = to_state_value } }
{ .type = TSParseActionTypeShift, .data = { .to_state = to_state_value } }
#define SHIFT_EXTRA() \
{ .type = TSParseActionTypeShiftExtra }
{ .type = TSParseActionTypeShiftExtra }
#define REDUCE_EXTRA(symbol_val) \
{ .type = TSParseActionTypeReduceExtra, .data = { .symbol = symbol_val } }
{ .type = TSParseActionTypeReduceExtra, .data = { .symbol = symbol_val } }
#define REDUCE(symbol_val, child_count_val) \
{ .type = TSParseActionTypeReduce, .data = { .symbol = symbol_val, .child_count = child_count_val } }
{ .type = TSParseActionTypeReduce, .data = { .symbol = symbol_val, .child_count = child_count_val } }
#define ACCEPT_INPUT() \
{ .type = TSParseActionTypeAccept }
{ .type = TSParseActionTypeAccept }
#define EXPORT_PARSER(constructor_name) \
TSParser * constructor_name() { \
TSParser * constructor_name() { \
return ts_parser_make((TSParserConfig) { \
.symbol_count = SYMBOL_COUNT, \
.hidden_symbol_flags = ts_hidden_symbol_flags, \
.parse_table = (const TSParseAction *)ts_parse_actions, \
.lex_states = ts_lex_states, \
.symbol_names = ts_symbol_names, \
.lex_fn = ts_lex, \
.symbol_count = SYMBOL_COUNT, \
.hidden_symbol_flags = ts_hidden_symbol_flags, \
.parse_table = (const TSParseAction *)ts_parse_actions, \
.lex_states = ts_lex_states, \
.symbol_names = ts_symbol_names, \
.lex_fn = ts_lex, \
}); \
}
}
#ifdef __cplusplus
}

View file

@ -8,16 +8,16 @@ extern "C" {
#include <stdlib.h>
typedef struct {
void *data;
const char * (* read_fn)(void *data, size_t *bytes_read);
int (* seek_fn)(void *data, size_t position);
void (* release_fn)(void *data);
void *data;
const char * (* read_fn)(void *data, size_t *bytes_read);
int (* seek_fn)(void *data, size_t position);
void (* release_fn)(void *data);
} TSInput;
typedef struct {
size_t position;
size_t bytes_inserted;
size_t bytes_removed;
size_t position;
size_t bytes_inserted;
size_t bytes_removed;
} TSInputEdit;
typedef unsigned short TSSymbol;

View file

@ -5,104 +5,104 @@
#include <string.h>
struct TSDocument {
TSParser *parser;
const TSTree *tree;
TSInput input;
size_t error_count;
TSParser *parser;
const TSTree *tree;
TSInput input;
size_t error_count;
};
TSDocument * ts_document_make() {
TSDocument *document = malloc(sizeof(TSDocument));
*document = (TSDocument) {
.input = (TSInput) {}
};
return document;
TSDocument *document = malloc(sizeof(TSDocument));
*document = (TSDocument) {
.input = (TSInput) {}
};
return document;
}
void ts_document_free(TSDocument *document) {
if (document->parser)
ts_parser_free(document->parser);
if (document->input.release_fn)
document->input.release_fn(document->input.data);
free(document);
if (document->parser)
ts_parser_free(document->parser);
if (document->input.release_fn)
document->input.release_fn(document->input.data);
free(document);
}
void ts_document_set_parser(TSDocument *document, TSParser *parser) {
if (document->parser)
ts_parser_free(document->parser);
document->parser = parser;
if (document->parser)
ts_parser_free(document->parser);
document->parser = parser;
}
const TSTree * ts_document_tree(const TSDocument *document) {
return document->tree;
return document->tree;
}
const char * ts_document_string(const TSDocument *document) {
return ts_tree_string(document->tree, ts_parser_config(document->parser).symbol_names);
return ts_tree_string(document->tree, ts_parser_config(document->parser).symbol_names);
}
void ts_document_set_input(TSDocument *document, TSInput input) {
document->input = input;
document->tree = ts_parser_parse(document->parser, document->input, NULL);
document->input = input;
document->tree = ts_parser_parse(document->parser, document->input, NULL);
}
void ts_document_edit(TSDocument *document, TSInputEdit edit) {
document->tree = ts_parser_parse(document->parser, document->input, &edit);
document->tree = ts_parser_parse(document->parser, document->input, &edit);
}
const char * ts_document_symbol_name(const TSDocument *document, const TSTree *tree) {
return ts_parser_config(document->parser).symbol_names[tree->symbol];
return ts_parser_config(document->parser).symbol_names[tree->symbol];
}
typedef struct {
const char *string;
size_t position;
size_t length;
const char *string;
size_t position;
size_t length;
} TSStringInput;
const char * ts_string_input_read(void *d, size_t *bytes_read) {
TSStringInput *data = (TSStringInput *)d;
if (data->position >= data->length) {
*bytes_read = 0;
return "";
}
size_t previous_position = data->position;
data->position = data->length;
*bytes_read = data->position - previous_position;
return data->string + previous_position;
TSStringInput *data = (TSStringInput *)d;
if (data->position >= data->length) {
*bytes_read = 0;
return "";
}
size_t previous_position = data->position;
data->position = data->length;
*bytes_read = data->position - previous_position;
return data->string + previous_position;
}
int ts_string_input_seek(void *d, size_t position) {
TSStringInput *data = (TSStringInput *)d;
data->position = position;
return (position < data->length);
TSStringInput *data = (TSStringInput *)d;
data->position = position;
return (position < data->length);
}
TSInput ts_string_input_make(const char *string) {
TSStringInput *data = malloc(sizeof(TSStringInput));
data->string = string;
data->position = 0;
data->length = strlen(string);
TSInput input = {
.data = (void *)data,
.read_fn = ts_string_input_read,
.seek_fn = ts_string_input_seek,
.release_fn = free,
};
return input;
TSStringInput *data = malloc(sizeof(TSStringInput));
data->string = string;
data->position = 0;
data->length = strlen(string);
TSInput input = {
.data = (void *)data,
.read_fn = ts_string_input_read,
.seek_fn = ts_string_input_seek,
.release_fn = free,
};
return input;
}
void ts_document_set_input_string(TSDocument *document, const char *text) {
ts_document_set_input(document, ts_string_input_make(text));
ts_document_set_input(document, ts_string_input_make(text));
}
TSNode * ts_document_root_node(const TSDocument *document) {
return ts_node_make_root(document->tree, document->parser->config.symbol_names);
return ts_node_make_root(document->tree, document->parser->config.symbol_names);
}
TSNode * ts_document_get_node(const TSDocument *document, size_t pos) {
TSNode *root = ts_document_root_node(document);
TSNode *result = ts_node_leaf_at_pos(root, pos);
ts_node_release(root);
return result;
TSNode *root = ts_document_root_node(document);
TSNode *result = ts_node_leaf_at_pos(root, pos);
ts_node_release(root);
return result;
}

View file

@ -2,42 +2,42 @@
#include "runtime/tree.h"
TSLexer ts_lexer_make() {
return (TSLexer) {
.chunk = NULL,
.debug = 0,
.chunk_start = 0,
.chunk_size = 0,
.position_in_chunk = 0,
.token_start_position = 0,
.token_end_position = 0,
.reached_end = 0
};
return (TSLexer) {
.chunk = NULL,
.debug = 0,
.chunk_start = 0,
.chunk_size = 0,
.position_in_chunk = 0,
.token_start_position = 0,
.token_end_position = 0,
.reached_end = 0
};
}
int ts_lexer_advance(TSLexer *lexer) {
static const char *empty_chunk = "";
if (lexer->position_in_chunk + 1 < lexer->chunk_size) {
lexer->position_in_chunk++;
} else {
lexer->chunk_start += lexer->chunk_size;
lexer->chunk = lexer->input.read_fn(lexer->input.data, &lexer->chunk_size);
lexer->position_in_chunk = 0;
if (lexer->reached_end) {
return 0;
}
if (lexer->chunk_size == 0) {
lexer->reached_end = 1;
lexer->chunk = empty_chunk;
}
static const char *empty_chunk = "";
if (lexer->position_in_chunk + 1 < lexer->chunk_size) {
lexer->position_in_chunk++;
} else {
lexer->chunk_start += lexer->chunk_size;
lexer->chunk = lexer->input.read_fn(lexer->input.data, &lexer->chunk_size);
lexer->position_in_chunk = 0;
if (lexer->reached_end) {
return 0;
}
return 1;
if (lexer->chunk_size == 0) {
lexer->reached_end = 1;
lexer->chunk = empty_chunk;
}
}
return 1;
}
TSTree * ts_lexer_build_node(TSLexer *lexer, TSSymbol symbol, int is_hidden) {
size_t current_position = ts_lexer_position(lexer);
size_t size = current_position - lexer->token_start_position;
size_t offset = lexer->token_start_position - lexer->token_end_position;
lexer->token_end_position = current_position;
return ts_tree_make_leaf(symbol, size, offset, is_hidden);
size_t current_position = ts_lexer_position(lexer);
size_t size = current_position - lexer->token_start_position;
size_t offset = lexer->token_start_position - lexer->token_end_position;
lexer->token_end_position = current_position;
return ts_tree_make_leaf(symbol, size, offset, is_hidden);
}

View file

@ -2,100 +2,100 @@
#include "runtime/tree.h"
TSNode * ts_node_make(const TSTree *tree, TSNode *parent, size_t index, size_t start_position, const char **names) {
if (parent) ts_node_retain(parent);
TSNode *result = malloc(sizeof(TSNode));
*result = (TSNode) {
.ref_count = 1,
.parent = parent,
.index = index,
.content = tree,
.start_position = start_position,
.names = names,
};
return result;
if (parent) ts_node_retain(parent);
TSNode *result = malloc(sizeof(TSNode));
*result = (TSNode) {
.ref_count = 1,
.parent = parent,
.index = index,
.content = tree,
.start_position = start_position,
.names = names,
};
return result;
}
TSNode * ts_node_make_root(const TSTree *tree, const char **names) {
while (ts_tree_is_wrapper(tree))
tree = tree->children[0];
return ts_node_make(tree, NULL, 0, 0, names);
while (ts_tree_is_wrapper(tree))
tree = tree->children[0];
return ts_node_make(tree, NULL, 0, 0, names);
}
void ts_node_retain(TSNode *node) {
node->ref_count++;
node->ref_count++;
}
void ts_node_release(TSNode *node) {
node->ref_count--;
if (node->ref_count == 0) {
if (node->parent) ts_node_release(node->parent);
free(node);
}
node->ref_count--;
if (node->ref_count == 0) {
if (node->parent) ts_node_release(node->parent);
free(node);
}
}
size_t ts_node_pos(const TSNode *node) {
return node->start_position + node->content->offset;
return node->start_position + node->content->offset;
}
size_t ts_node_size(const TSNode *node) {
return node->content->size;
return node->content->size;
}
int ts_node_eq(const TSNode *left, const TSNode *right) {
return ts_tree_equals(left->content, right->content);
return ts_tree_equals(left->content, right->content);
}
const char * ts_node_name(const TSNode *node) {
return node->names[node->content->symbol];
return node->names[node->content->symbol];
}
const char * ts_node_string(const TSNode *node) {
return ts_tree_string(node->content, node->names);
return ts_tree_string(node->content, node->names);
}
TSNode * ts_node_parent(TSNode *child) {
return child->parent;
return child->parent;
}
TSNode * ts_node_prev_sibling(TSNode *child) {
return ts_node_child(child->parent, child->index - 1);
return ts_node_child(child->parent, child->index - 1);
}
TSNode * ts_node_next_sibling(TSNode *child) {
return ts_node_child(child->parent, child->index + 1);
return ts_node_child(child->parent, child->index + 1);
}
size_t ts_node_child_count(const TSNode *parent) {
size_t result;
ts_tree_visible_children(parent->content, &result);
return result;
size_t result;
ts_tree_visible_children(parent->content, &result);
return result;
}
TSNode * ts_node_child(TSNode *parent, size_t index) {
size_t child_count;
TSChildWithPosition *children = ts_tree_visible_children(parent->content, &child_count);
if (child_count <= index)
return NULL;
size_t position = parent->start_position + children[index].position;
return ts_node_make(children[index].tree, parent, index, position, parent->names);
size_t child_count;
TSChildWithPosition *children = ts_tree_visible_children(parent->content, &child_count);
if (child_count <= index)
return NULL;
size_t position = parent->start_position + children[index].position;
return ts_node_make(children[index].tree, parent, index, position, parent->names);
}
TSNode * ts_node_leaf_at_pos(TSNode *parent, size_t position) {
size_t child_count;
TSChildWithPosition *children = ts_tree_visible_children(parent->content, &child_count);
for (size_t i = 0; i < child_count; i++) {
TSChildWithPosition child = children[i];
size_t child_left = child.position + child.tree->offset;
if (child_left > position)
break;
if (child_left + child.tree->size > position) {
TSNode *node = ts_node_make(child.tree, parent, i, child.position, parent->names);
TSNode *result = ts_node_leaf_at_pos(node, position);
ts_node_release(node);
return result;
}
size_t child_count;
TSChildWithPosition *children = ts_tree_visible_children(parent->content, &child_count);
for (size_t i = 0; i < child_count; i++) {
TSChildWithPosition child = children[i];
size_t child_left = child.position + child.tree->offset;
if (child_left > position)
break;
if (child_left + child.tree->size > position) {
TSNode *node = ts_node_make(child.tree, parent, i, child.position, parent->names);
TSNode *result = ts_node_leaf_at_pos(node, position);
ts_node_release(node);
return result;
}
}
ts_node_retain(parent);
return parent;
ts_node_retain(parent);
return parent;
}

View file

@ -5,12 +5,12 @@
#include "runtime/tree.h"
struct TSNode {
size_t ref_count;
size_t start_position;
size_t index;
const TSTree *content;
struct TSNode *parent;
const char **names;
size_t ref_count;
size_t start_position;
size_t index;
const TSTree *content;
struct TSNode *parent;
const char **names;
};
TSNode * ts_node_make(const TSTree *tree, TSNode *parent, size_t index, size_t start_position, const char **names);

View file

@ -8,56 +8,56 @@
*/
static const TSParseAction * actions_for_state(TSParserConfig config, TSStateId state) {
return config.parse_table + (state * config.symbol_count);
return config.parse_table + (state * config.symbol_count);
}
static size_t breakdown_stack(TSParser *parser, TSInputEdit *edit) {
if (!edit) return 0;
if (!edit) return 0;
TSStack *stack = &parser->stack;
size_t position = 0;
TSStack *stack = &parser->stack;
size_t position = 0;
for (;;) {
TSTree *node = ts_stack_top_node(stack);
if (!node) break;
for (;;) {
TSTree *node = ts_stack_top_node(stack);
if (!node) break;
position = ts_stack_right_position(stack);
size_t child_count;
TSTree **children = ts_tree_children(node, &child_count);
if (position <= edit->position && !children) break;
position = ts_stack_right_position(stack);
size_t child_count;
TSTree **children = ts_tree_children(node, &child_count);
if (position <= edit->position && !children) break;
stack->size--;
position -= ts_tree_total_size(node);
stack->size--;
position -= ts_tree_total_size(node);
for (size_t i = 0; i < child_count && position < edit->position; i++) {
TSTree *child = children[i];
TSStateId state = ts_stack_top_state(stack);
TSStateId next_state = actions_for_state(parser->config, state)[child->symbol].data.to_state;
ts_stack_push(stack, next_state, child);
ts_tree_retain(child);
position += ts_tree_total_size(child);
}
ts_tree_release(node);
for (size_t i = 0; i < child_count && position < edit->position; i++) {
TSTree *child = children[i];
TSStateId state = ts_stack_top_state(stack);
TSStateId next_state = actions_for_state(parser->config, state)[child->symbol].data.to_state;
ts_stack_push(stack, next_state, child);
ts_tree_retain(child);
position += ts_tree_total_size(child);
}
return position;
ts_tree_release(node);
}
return position;
}
static TSSymbol * expected_symbols(TSParser *parser, size_t *count) {
*count = 0;
const TSParseAction *actions = actions_for_state(parser->config, ts_stack_top_state(&parser->stack));
for (size_t i = 0; i < parser->config.symbol_count; i++)
if (actions[i].type != TSParseActionTypeError)
(*count)++;
*count = 0;
const TSParseAction *actions = actions_for_state(parser->config, ts_stack_top_state(&parser->stack));
for (size_t i = 0; i < parser->config.symbol_count; i++)
if (actions[i].type != TSParseActionTypeError)
(*count)++;
size_t n = 0;
TSSymbol *result = malloc(*count * sizeof(*result));
for (TSSymbol i = 0; i < parser->config.symbol_count; i++)
if (actions[i].type != TSParseActionTypeError)
result[n++] = i;
size_t n = 0;
TSSymbol *result = malloc(*count * sizeof(*result));
for (TSSymbol i = 0; i < parser->config.symbol_count; i++)
if (actions[i].type != TSParseActionTypeError)
result[n++] = i;
return result;
return result;
}
/*
@ -65,183 +65,185 @@ static TSSymbol * expected_symbols(TSParser *parser, size_t *count) {
*/
TSParser * ts_parser_make(TSParserConfig config) {
TSParser *result = malloc(sizeof(*result));
*result = (TSParser) {
.lexer = ts_lexer_make(),
.stack = ts_stack_make(),
.debug = 0,
.config = config,
};
return result;
TSParser *result = malloc(sizeof(*result));
*result = (TSParser) {
.lexer = ts_lexer_make(),
.stack = ts_stack_make(),
.debug = 0,
.config = config,
};
return result;
}
void ts_parser_free(TSParser *parser) {
if (parser->lookahead) ts_tree_release(parser->lookahead);
if (parser->next_lookahead) ts_tree_release(parser->next_lookahead);
ts_stack_delete(&parser->stack);
free(parser);
if (parser->lookahead) ts_tree_release(parser->lookahead);
if (parser->next_lookahead) ts_tree_release(parser->next_lookahead);
ts_stack_delete(&parser->stack);
free(parser);
}
void ts_parser_start(TSParser *parser, TSInput input, TSInputEdit *edit) {
if (!edit) ts_stack_shrink(&parser->stack, 0);
parser->lookahead = NULL;
parser->next_lookahead = NULL;
if (!edit) ts_stack_shrink(&parser->stack, 0);
parser->lookahead = NULL;
parser->next_lookahead = NULL;
size_t position = breakdown_stack(parser, edit);
input.seek_fn(input.data, position);
size_t position = breakdown_stack(parser, edit);
input.seek_fn(input.data, position);
parser->lexer = ts_lexer_make();
parser->lexer.input = input;
ts_lexer_advance(&parser->lexer);
parser->lexer = ts_lexer_make();
parser->lexer.input = input;
ts_lexer_advance(&parser->lexer);
}
void ts_parser_shift(TSParser *parser, TSStateId parse_state) {
if (ts_tree_is_extra(parser->lookahead))
parse_state = ts_stack_top_state(&parser->stack);
ts_stack_push(&parser->stack, parse_state, parser->lookahead);
parser->lookahead = parser->next_lookahead;
parser->next_lookahead = NULL;
if (ts_tree_is_extra(parser->lookahead))
parse_state = ts_stack_top_state(&parser->stack);
ts_stack_push(&parser->stack, parse_state, parser->lookahead);
parser->lookahead = parser->next_lookahead;
parser->next_lookahead = NULL;
}
void ts_parser_shift_extra(TSParser *parser) {
ts_tree_set_extra(parser->lookahead);
ts_parser_shift(parser, 0);
ts_tree_set_extra(parser->lookahead);
ts_parser_shift(parser, 0);
}
void ts_parser_reduce(TSParser *parser, TSSymbol symbol, size_t child_count) {
parser->next_lookahead = parser->lookahead;
parser->lookahead = ts_stack_reduce(
&parser->stack,
symbol,
child_count,
parser->config.hidden_symbol_flags, 1);
parser->next_lookahead = parser->lookahead;
parser->lookahead = ts_stack_reduce(
&parser->stack,
symbol,
child_count,
parser->config.hidden_symbol_flags, 1);
}
int ts_parser_reduce_extra(TSParser *parser, TSSymbol symbol) {
TSTree *top_node = ts_stack_top_node(&parser->stack);
if (top_node->symbol == symbol && !ts_tree_is_extra(top_node)) {
ts_parser_reduce(parser, symbol, 1);
ts_tree_set_extra(parser->lookahead);
return 1;
} else {
return 0;
}
TSTree *top_node = ts_stack_top_node(&parser->stack);
if (top_node->symbol == symbol && !ts_tree_is_extra(top_node)) {
ts_parser_reduce(parser, symbol, 1);
ts_tree_set_extra(parser->lookahead);
return 1;
} else {
return 0;
}
}
int ts_parser_handle_error(TSParser *parser) {
size_t count = 0;
const TSSymbol *inputs = expected_symbols(parser, &count);
TSTree *error = ts_tree_make_error(ts_lexer_lookahead_char(&parser->lexer),
count,
inputs,
0,
0);
size_t count = 0;
const TSSymbol *inputs = expected_symbols(parser, &count);
TSTree *error = ts_tree_make_error(
ts_lexer_lookahead_char(&parser->lexer),
count,
inputs,
0,
0);
for (;;) {
ts_tree_release(parser->lookahead);
size_t position = ts_lexer_position(&parser->lexer);
parser->lookahead = parser->config.lex_fn(parser, ts_lex_state_error);
for (;;) {
ts_tree_release(parser->lookahead);
size_t position = ts_lexer_position(&parser->lexer);
parser->lookahead = parser->config.lex_fn(parser, ts_lex_state_error);
int at_end = 0;
if (ts_lexer_position(&parser->lexer) == position)
at_end = !ts_lexer_advance(&parser->lexer);
int at_end = 0;
if (ts_lexer_position(&parser->lexer) == position)
at_end = !ts_lexer_advance(&parser->lexer);
if (at_end || parser->lookahead->symbol == ts_builtin_sym_end) {
ts_stack_push(&parser->stack, 0, error);
return 0;
}
/*
* Unwind the stack, looking for a state in which this token
* may appear after an error.
*/
for (size_t j = 0; j < parser->stack.size; j++) {
size_t i = parser->stack.size - 1 - j;
TSStateId stack_state = parser->stack.entries[i].state;
TSParseAction action_on_error = actions_for_state(parser->config, stack_state)[ts_builtin_sym_error];
if (action_on_error.type == TSParseActionTypeShift) {
TSStateId state_after_error = action_on_error.data.to_state;
if (actions_for_state(parser->config, state_after_error)[parser->lookahead->symbol].type != TSParseActionTypeError) {
ts_stack_shrink(&parser->stack, i + 1);
ts_stack_push(&parser->stack, state_after_error, error);
return 1;
}
}
}
if (at_end || parser->lookahead->symbol == ts_builtin_sym_end) {
ts_stack_push(&parser->stack, 0, error);
return 0;
}
/*
* Unwind the stack, looking for a state in which this token
* may appear after an error.
*/
for (size_t j = 0; j < parser->stack.size; j++) {
size_t i = parser->stack.size - 1 - j;
TSStateId stack_state = parser->stack.entries[i].state;
TSParseAction action_on_error = actions_for_state(parser->config, stack_state)[ts_builtin_sym_error];
if (action_on_error.type == TSParseActionTypeShift) {
TSStateId state_after_error = action_on_error.data.to_state;
if (actions_for_state(parser->config, state_after_error)[parser->lookahead->symbol].type != TSParseActionTypeError) {
ts_stack_shrink(&parser->stack, i + 1);
ts_stack_push(&parser->stack, state_after_error, error);
return 1;
}
}
}
}
}
TSTree * ts_parser_tree_root(TSParser *parser) {
TSStack *stack = &parser->stack;
size_t node_count = 0;
for (size_t i = 0; i < stack->size; i++) {
TSTree *node = stack->entries[i].node;
if (!parser->config.hidden_symbol_flags[node->symbol])
node_count++;
}
TSStack *stack = &parser->stack;
size_t node_count = 0;
for (size_t i = 0; i < stack->size; i++) {
TSTree *node = stack->entries[i].node;
if (!parser->config.hidden_symbol_flags[node->symbol])
node_count++;
}
if (node_count > 1)
return ts_stack_reduce(stack, 2, stack->size, parser->config.hidden_symbol_flags, 0);
else
return ts_stack_top_node(stack);
if (node_count > 1)
return ts_stack_reduce(stack, 2, stack->size, parser->config.hidden_symbol_flags, 0);
else
return ts_stack_top_node(stack);
}
TSParseAction ts_parser_next_action(TSParser *parser) {
TSStateId state = ts_stack_top_state(&parser->stack);
if (!parser->lookahead)
parser->lookahead = parser->config.lex_fn(parser, parser->config.lex_states[state]);
return actions_for_state(parser->config, state)[parser->lookahead->symbol];
TSStateId state = ts_stack_top_state(&parser->stack);
if (!parser->lookahead)
parser->lookahead = parser->config.lex_fn(parser, parser->config.lex_states[state]);
return actions_for_state(parser->config, state)[parser->lookahead->symbol];
}
#define DEBUG_PARSE(...) \
if (parser->debug) { fprintf(stderr, "\n" __VA_ARGS__); }
if (parser->debug) { fprintf(stderr, "\n" __VA_ARGS__); }
TSTree * ts_parser_step(TSParser *parser) {
TSParseAction action = ts_parser_next_action(parser);
DEBUG_PARSE("LOOKAHEAD %s", parser->config.symbol_names[parser->lookahead->symbol]);
switch (action.type) {
case TSParseActionTypeShift:
DEBUG_PARSE("SHIFT %d", action.data.to_state);
ts_parser_shift(parser, action.data.to_state);
return NULL;
case TSParseActionTypeShiftExtra:
DEBUG_PARSE("SHIFT EXTRA");
ts_parser_shift_extra(parser);
return NULL;
case TSParseActionTypeReduce:
DEBUG_PARSE("REDUCE %s %d", parser->config.symbol_names[action.data.symbol], action.data.child_count);
ts_parser_reduce(parser, action.data.symbol, action.data.child_count);
return NULL;
case TSParseActionTypeReduceExtra:
if (!ts_parser_reduce_extra(parser, action.data.symbol))
goto error;
DEBUG_PARSE("REDUCE EXTRA");
return NULL;
case TSParseActionTypeAccept:
DEBUG_PARSE("ACCEPT");
return ts_parser_tree_root(parser);
case TSParseActionTypeError:
goto error;
default:
return NULL;
}
TSParseAction action = ts_parser_next_action(parser);
DEBUG_PARSE("LOOKAHEAD %s", parser->config.symbol_names[parser->lookahead->symbol]);
switch (action.type) {
case TSParseActionTypeShift:
DEBUG_PARSE("SHIFT %d", action.data.to_state);
ts_parser_shift(parser, action.data.to_state);
return NULL;
case TSParseActionTypeShiftExtra:
DEBUG_PARSE("SHIFT EXTRA");
ts_parser_shift_extra(parser);
return NULL;
case TSParseActionTypeReduce:
DEBUG_PARSE("REDUCE %s %d", parser->config.symbol_names[action.data.symbol], action.data.child_count);
ts_parser_reduce(parser, action.data.symbol, action.data.child_count);
return NULL;
case TSParseActionTypeReduceExtra:
if (!ts_parser_reduce_extra(parser, action.data.symbol))
goto error;
DEBUG_PARSE("REDUCE EXTRA");
return NULL;
case TSParseActionTypeAccept:
DEBUG_PARSE("ACCEPT");
return ts_parser_tree_root(parser);
case TSParseActionTypeError:
goto error;
default:
return NULL;
}
error:
DEBUG_PARSE("ERROR");
if (!ts_parser_handle_error(parser))
return ts_parser_tree_root(parser);
else
return NULL;
DEBUG_PARSE("ERROR");
if (!ts_parser_handle_error(parser))
return ts_parser_tree_root(parser);
else
return NULL;
}
const TSTree * ts_parser_parse(TSParser *parser, TSInput input, TSInputEdit *edit) {
ts_parser_start(parser, input, edit);
ts_parser_start(parser, input, edit);
for (;;) {
const TSTree *tree = ts_parser_step(parser);
if (tree) return tree;
}
for (;;) {
const TSTree *tree = ts_parser_step(parser);
if (tree) return tree;
}
}
TSParserConfig ts_parser_config(TSParser *parser) {
return parser->config;
return parser->config;
}

View file

@ -7,77 +7,78 @@ static size_t INITIAL_STACK_SIZE = 100;
static TSStateId INITIAL_STATE = 0;
TSStack ts_stack_make() {
TSStack result = {
.entries = calloc(INITIAL_STACK_SIZE, sizeof(*result.entries)),
.size = 0,
};
return result;
TSStack result = {
.entries = calloc(INITIAL_STACK_SIZE, sizeof(*result.entries)),
.size = 0,
};
return result;
}
void ts_stack_delete(TSStack *stack) {
ts_stack_shrink(stack, 0);
free(stack->entries);
ts_stack_shrink(stack, 0);
free(stack->entries);
}
TSStateId ts_stack_top_state(const TSStack *stack) {
if (stack->size == 0) return INITIAL_STATE;
return stack->entries[stack->size - 1].state;
if (stack->size == 0)
return INITIAL_STATE;
return stack->entries[stack->size - 1].state;
}
TSTree * ts_stack_top_node(const TSStack *stack) {
if (stack->size == 0) return NULL;
return stack->entries[stack->size - 1].node;
if (stack->size == 0)
return NULL;
return stack->entries[stack->size - 1].node;
}
void ts_stack_push(TSStack *stack, TSStateId state, TSTree *node) {
stack->entries[stack->size].state = state;
stack->entries[stack->size].node = node;
stack->size++;
ts_tree_retain(node);
stack->entries[stack->size].state = state;
stack->entries[stack->size].node = node;
stack->size++;
ts_tree_retain(node);
}
void ts_stack_shrink(TSStack *stack, size_t new_size) {
for (size_t i = new_size; i < stack->size; i++)
ts_tree_release(stack->entries[i].node);
stack->size = new_size;
for (size_t i = new_size; i < stack->size; i++)
ts_tree_release(stack->entries[i].node);
stack->size = new_size;
}
size_t ts_stack_right_position(const TSStack *stack) {
size_t result = 0;
for (size_t i = 0; i < stack->size; i++) {
TSTree *node = stack->entries[i].node;
result += ts_tree_total_size(node);
}
return result;
size_t result = 0;
for (size_t i = 0; i < stack->size; i++) {
TSTree *node = stack->entries[i].node;
result += ts_tree_total_size(node);
}
return result;
}
TSTree * ts_stack_reduce(TSStack *stack,
TSSymbol symbol,
size_t child_count,
const int *hidden_symbol_flags,
int dont_count_extras) {
TSSymbol symbol,
size_t child_count,
const int *hidden_symbol_flags,
int dont_count_extras) {
// First, walk down the stack to determine which symbols will be reduced.
// The child node count is known ahead of time, but some children may be
// extra tokens, which don't count towards the child node count.
for (size_t i = 0; i < child_count; i++) {
TSTree *child = stack->entries[stack->size - 1 - i].node;
if (dont_count_extras && ts_tree_is_extra(child))
child_count++;
}
// First, walk down the stack to determine which symbols will be reduced.
// The child node count is known ahead of time, but some children may be
// extra tokens, which don't count towards the child node count.
for (size_t i = 0; i < child_count; i++) {
TSTree *child = stack->entries[stack->size - 1 - i].node;
if (dont_count_extras && ts_tree_is_extra(child))
child_count++;
}
size_t start_index = stack->size - child_count;
TSTree **children = calloc(child_count, sizeof(TSTree *));
for (size_t i = 0; i < child_count; i++)
children[i] = stack->entries[start_index + i].node;
size_t start_index = stack->size - child_count;
TSTree **children = calloc(child_count, sizeof(TSTree *));
for (size_t i = 0; i < child_count; i++)
children[i] = stack->entries[start_index + i].node;
TSTree *lookahead = ts_tree_make_node(
symbol,
child_count,
children,
hidden_symbol_flags[symbol]
);
TSTree *lookahead = ts_tree_make_node(
symbol,
child_count,
children,
hidden_symbol_flags[symbol]);
ts_stack_shrink(stack, stack->size - child_count);
return lookahead;
ts_stack_shrink(stack, stack->size - child_count);
return lookahead;
}

View file

@ -4,181 +4,181 @@
#include "runtime/tree.h"
static TSTree * ts_tree_make(TSSymbol symbol, size_t size, size_t offset, int is_hidden) {
TSTree *result = malloc(sizeof(TSTree));
*result = (TSTree) {
.ref_count = 1,
.symbol = symbol,
.size = size,
.offset = offset,
.options = is_hidden ? TSTreeOptionsHidden : 0,
};
return result;
TSTree *result = malloc(sizeof(TSTree));
*result = (TSTree) {
.ref_count = 1,
.symbol = symbol,
.size = size,
.offset = offset,
.options = is_hidden ? TSTreeOptionsHidden : 0,
};
return result;
}
TSTree * ts_tree_make_leaf(TSSymbol symbol, size_t size, size_t offset, int is_hidden) {
TSTree *result = ts_tree_make(symbol, size, offset, is_hidden);
result->child_count = 0;
result->children = NULL;
return result;
TSTree *result = ts_tree_make(symbol, size, offset, is_hidden);
result->child_count = 0;
result->children = NULL;
return result;
}
TSTree * ts_tree_make_node(TSSymbol symbol, size_t child_count, TSTree **children, int is_hidden) {
size_t size = 0, offset = 0, visible_child_count = 0;
for (size_t i = 0; i < child_count; i++) {
TSTree *child = children[i];
ts_tree_retain(child);
if (i == 0) {
offset = child->offset;
size = child->size;
} else {
size += child->offset + child->size;
}
if (ts_tree_is_visible(child))
visible_child_count++;
else
visible_child_count += ts_tree_visible_child_count(child);
size_t size = 0, offset = 0, visible_child_count = 0;
for (size_t i = 0; i < child_count; i++) {
TSTree *child = children[i];
ts_tree_retain(child);
if (i == 0) {
offset = child->offset;
size = child->size;
} else {
size += child->offset + child->size;
}
TSTreeOptions options = 0;
if (is_hidden)
options |= TSTreeOptionsHidden;
if (child_count == 1 && (ts_tree_is_visible(children[0]) || ts_tree_is_wrapper(children[0])))
options |= (TSTreeOptionsWrapper | TSTreeOptionsHidden);
if (ts_tree_is_visible(child))
visible_child_count++;
else
visible_child_count += ts_tree_visible_child_count(child);
}
TSTree *result = malloc(sizeof(TSTree) + (visible_child_count * sizeof(TSChildWithPosition)));
*result = (TSTree) {
.ref_count = 1,
.symbol = symbol,
.size = size,
.offset = offset,
.options = options,
.children = children,
.child_count = child_count,
.visible_child_count = visible_child_count,
};
TSTreeOptions options = 0;
if (is_hidden)
options |= TSTreeOptionsHidden;
if (child_count == 1 && (ts_tree_is_visible(children[0]) || ts_tree_is_wrapper(children[0])))
options |= (TSTreeOptionsWrapper | TSTreeOptionsHidden);
TSChildWithPosition *visible_children = ts_tree_visible_children(result, NULL);
TSTree *result = malloc(sizeof(TSTree) + (visible_child_count * sizeof(TSChildWithPosition)));
*result = (TSTree) {
.ref_count = 1,
.symbol = symbol,
.size = size,
.offset = offset,
.options = options,
.children = children,
.child_count = child_count,
.visible_child_count = visible_child_count,
};
for (size_t i = 0, visible_i = 0, child_position = 0; i < child_count; i++) {
TSTree *child = children[i];
if (ts_tree_is_visible(child)) {
visible_children[visible_i] = (TSChildWithPosition) {
.tree = child,
.position = child_position
};
visible_i++;
} else {
size_t granchild_count = 0;
TSChildWithPosition *grandchildren = ts_tree_visible_children(child, &granchild_count);
for (size_t j = 0; j < granchild_count; j++) {
visible_children[visible_i] = (TSChildWithPosition) {
.tree = grandchildren[j].tree,
.position = grandchildren[j].position + child_position
};
visible_i++;
}
}
TSChildWithPosition *visible_children = ts_tree_visible_children(result, NULL);
child_position += child->offset + child->size;
for (size_t i = 0, visible_i = 0, child_position = 0; i < child_count; i++) {
TSTree *child = children[i];
if (ts_tree_is_visible(child)) {
visible_children[visible_i] = (TSChildWithPosition) {
.tree = child,
.position = child_position
};
visible_i++;
} else {
size_t granchild_count = 0;
TSChildWithPosition *grandchildren = ts_tree_visible_children(child, &granchild_count);
for (size_t j = 0; j < granchild_count; j++) {
visible_children[visible_i] = (TSChildWithPosition) {
.tree = grandchildren[j].tree,
.position = grandchildren[j].position + child_position
};
visible_i++;
}
}
return result;
child_position += child->offset + child->size;
}
return result;
}
TSTree * ts_tree_make_error(char lookahead_char, size_t expected_input_count, const TSSymbol *expected_inputs, size_t size, size_t offset) {
TSTree *result = ts_tree_make(ts_builtin_sym_error, size, offset, 0);
result->lookahead_char = lookahead_char;
result->expected_input_count = expected_input_count;
result->expected_inputs = expected_inputs;
return result;
TSTree *result = ts_tree_make(ts_builtin_sym_error, size, offset, 0);
result->lookahead_char = lookahead_char;
result->expected_input_count = expected_input_count;
result->expected_inputs = expected_inputs;
return result;
}
void ts_tree_retain(TSTree *tree) {
tree->ref_count++;
tree->ref_count++;
}
void ts_tree_release(TSTree *tree) {
tree->ref_count--;
if (tree->ref_count == 0) {
size_t count;
TSTree **children = ts_tree_children(tree, &count);
for (size_t i = 0; i < count; i++)
ts_tree_release(children[i]);
free(tree->children);
free(tree);
}
tree->ref_count--;
if (tree->ref_count == 0) {
size_t count;
TSTree **children = ts_tree_children(tree, &count);
for (size_t i = 0; i < count; i++)
ts_tree_release(children[i]);
free(tree->children);
free(tree);
}
}
size_t ts_tree_total_size(const TSTree *tree) {
return tree->offset + tree->size;
return tree->offset + tree->size;
}
int ts_tree_equals(const TSTree *node1, const TSTree *node2) {
if (node1->symbol != node2->symbol) return 0;
if (node1->symbol == ts_builtin_sym_error) {
// check error equality
} else {
if (node1->child_count != node2->child_count) return 0;
for (size_t i = 0; i < node1->child_count; i++)
if (!ts_tree_equals(node1->children[i], node2->children[i])) return 0;
}
return 1;
if (node1->symbol != node2->symbol) return 0;
if (node1->symbol == ts_builtin_sym_error) {
// check error equality
} else {
if (node1->child_count != node2->child_count) return 0;
for (size_t i = 0; i < node1->child_count; i++)
if (!ts_tree_equals(node1->children[i], node2->children[i])) return 0;
}
return 1;
}
TSTree ** ts_tree_children(const TSTree *tree, size_t *count) {
if (!tree || tree->symbol == ts_builtin_sym_error) {
if (count) *count = 0;
return NULL;
}
if (count) *count = tree->child_count;
return tree->children;
if (!tree || tree->symbol == ts_builtin_sym_error) {
if (count) *count = 0;
return NULL;
}
if (count) *count = tree->child_count;
return tree->children;
}
static size_t write_lookahead_to_string(char *string, size_t limit, char lookahead) {
switch (lookahead) {
case '\0':
return snprintf(string, limit, "<EOF>");
default:
return snprintf(string, limit, "'%c'", lookahead);
}
switch (lookahead) {
case '\0':
return snprintf(string, limit, "<EOF>");
default:
return snprintf(string, limit, "'%c'", lookahead);
}
}
static size_t tree_write_to_string(const TSTree *tree, const char **symbol_names, char *string, size_t limit, int is_root) {
char *cursor = string;
char **writer = (limit > 0) ? &cursor : &string;
int visible = ts_tree_is_visible(tree);
char *cursor = string;
char **writer = (limit > 0) ? &cursor : &string;
int visible = ts_tree_is_visible(tree);
if (visible && !is_root)
cursor += snprintf(*writer, limit, " ");
if (!tree)
return snprintf(*writer, limit, "(NULL)");
if (tree->symbol == ts_builtin_sym_error) {
cursor += snprintf(*writer, limit, "(ERROR ");
cursor += write_lookahead_to_string(*writer, limit, tree->lookahead_char);
cursor += snprintf(*writer, limit, ")");
return cursor - string;
}
if (visible) {
cursor += snprintf(*writer, limit, "(%s", symbol_names[tree->symbol]);
is_root = 0;
}
for (size_t i = 0; i < tree->child_count; i++)
cursor += tree_write_to_string(tree->children[i], symbol_names, *writer, limit, is_root);
if (visible)
cursor += snprintf(*writer, limit, ")");
if (visible && !is_root)
cursor += snprintf(*writer, limit, " ");
if (!tree)
return snprintf(*writer, limit, "(NULL)");
if (tree->symbol == ts_builtin_sym_error) {
cursor += snprintf(*writer, limit, "(ERROR ");
cursor += write_lookahead_to_string(*writer, limit, tree->lookahead_char);
cursor += snprintf(*writer, limit, ")");
return cursor - string;
}
if (visible) {
cursor += snprintf(*writer, limit, "(%s", symbol_names[tree->symbol]);
is_root = 0;
}
for (size_t i = 0; i < tree->child_count; i++)
cursor += tree_write_to_string(tree->children[i], symbol_names, *writer, limit, is_root);
if (visible)
cursor += snprintf(*writer, limit, ")");
return cursor - string;
}
char * ts_tree_string(const TSTree *tree, const char **symbol_names) {
static char SCRATCH_STRING[1];
size_t size = tree_write_to_string(tree, symbol_names, SCRATCH_STRING, 0, 1) + 1;
char *result = malloc(size * sizeof(char));
tree_write_to_string(tree, symbol_names, result, size, 1);
return result;
static char SCRATCH_STRING[1];
size_t size = tree_write_to_string(tree, symbol_names, SCRATCH_STRING, 0, 1) + 1;
char *result = malloc(size * sizeof(char));
tree_write_to_string(tree, symbol_names, result, size, 1);
return result;
}

View file

@ -8,67 +8,67 @@ extern "C" {
#include "tree_sitter/runtime.h"
typedef enum {
TSTreeOptionsHidden = 1,
TSTreeOptionsExtra = 2,
TSTreeOptionsWrapper = 4,
TSTreeOptionsHidden = 1,
TSTreeOptionsExtra = 2,
TSTreeOptionsWrapper = 4,
} TSTreeOptions;
struct TSTree {
TSSymbol symbol;
TSTreeOptions options;
size_t ref_count;
size_t offset;
size_t size;
union {
struct {
size_t child_count;
struct TSTree **children;
size_t visible_child_count;
};
struct {
size_t expected_input_count;
const TSSymbol *expected_inputs;
char lookahead_char;
};
TSSymbol symbol;
TSTreeOptions options;
size_t ref_count;
size_t offset;
size_t size;
union {
struct {
size_t child_count;
struct TSTree **children;
size_t visible_child_count;
};
struct {
size_t expected_input_count;
const TSSymbol *expected_inputs;
char lookahead_char;
};
};
};
typedef struct {
TSTree *tree;
size_t position;
TSTree *tree;
size_t position;
} TSChildWithPosition;
static inline int ts_tree_is_extra(const TSTree *tree) {
return (tree->options & TSTreeOptionsExtra);
return (tree->options & TSTreeOptionsExtra);
}
static inline int ts_tree_is_visible(const TSTree *tree) {
return !(tree->options & TSTreeOptionsHidden);
return !(tree->options & TSTreeOptionsHidden);
}
static inline void ts_tree_set_extra(TSTree *tree) {
tree->options = (TSTreeOptions)(tree->options | TSTreeOptionsExtra);
tree->options = (TSTreeOptions)(tree->options | TSTreeOptionsExtra);
}
static inline int ts_tree_is_wrapper(const TSTree *tree) {
return (tree->options & TSTreeOptionsWrapper);
return (tree->options & TSTreeOptionsWrapper);
}
static inline size_t ts_tree_visible_child_count(const TSTree *tree) {
if (tree->symbol == ts_builtin_sym_error)
return 0;
else
return tree->visible_child_count;
if (tree->symbol == ts_builtin_sym_error)
return 0;
else
return tree->visible_child_count;
}
static inline TSChildWithPosition * ts_tree_visible_children(const TSTree *tree, size_t *count) {
if (tree->symbol == ts_builtin_sym_error || tree->visible_child_count == 0) {
if (count) *count = 0;
return NULL;
} else {
if (count) *count = tree->visible_child_count;
return (TSChildWithPosition *)(tree + 1);
}
if (tree->symbol == ts_builtin_sym_error || tree->visible_child_count == 0) {
if (count) *count = 0;
return NULL;
} else {
if (count) *count = tree->visible_child_count;
return (TSChildWithPosition *)(tree + 1);
}
}
TSTree * ts_tree_make_leaf(TSSymbol symbol, size_t size, size_t offset, int is_hidden);