221 lines
5.9 KiB
C
221 lines
5.9 KiB
C
#include <emscripten.h>
|
|
#include <tree_sitter/api.h>
|
|
#include <stdio.h>
|
|
|
|
/*****************************/
|
|
/* Section - Data marshaling */
|
|
/*****************************/
|
|
|
|
static const uint32_t INPUT_BUFFER_SIZE = 10 * 1024;
|
|
|
|
const void *TRANSFER_BUFFER[12] = {
|
|
NULL, NULL, NULL, NULL,
|
|
NULL, NULL, NULL, NULL,
|
|
NULL, NULL, NULL, NULL,
|
|
};
|
|
|
|
void *ts_init() {
|
|
return TRANSFER_BUFFER;
|
|
}
|
|
|
|
static uint32_t code_unit_to_byte(uint32_t unit) {
|
|
return unit << 1;
|
|
}
|
|
|
|
static uint32_t byte_to_code_unit(uint32_t byte) {
|
|
return byte >> 1;
|
|
}
|
|
|
|
static void marshal_node(TSNode node) {
|
|
TRANSFER_BUFFER[0] = (const void *)node.id;
|
|
TRANSFER_BUFFER[1] = (const void *)node.context[0];
|
|
TRANSFER_BUFFER[2] = (const void *)node.context[1];
|
|
TRANSFER_BUFFER[3] = (const void *)node.context[2];
|
|
TRANSFER_BUFFER[4] = (const void *)node.context[3];
|
|
}
|
|
|
|
static TSNode unmarshal_node(const TSTree *tree) {
|
|
TSNode node;
|
|
node.id = TRANSFER_BUFFER[0];
|
|
node.context[0] = (uint32_t)TRANSFER_BUFFER[1];
|
|
node.context[1] = (uint32_t)TRANSFER_BUFFER[2];
|
|
node.context[2] = (uint32_t)TRANSFER_BUFFER[3];
|
|
node.context[3] = (uint32_t)TRANSFER_BUFFER[4];
|
|
node.tree = tree;
|
|
return node;
|
|
}
|
|
|
|
static void marshal_point(TSPoint point) {
|
|
TRANSFER_BUFFER[0] = (const void *)point.row;
|
|
TRANSFER_BUFFER[1] = (const void *)byte_to_code_unit(point.column);
|
|
}
|
|
|
|
static TSPoint unmarshal_point(const void **address) {
|
|
TSPoint point;
|
|
point.row = (uint32_t)address[0];
|
|
point.column = code_unit_to_byte((uint32_t)address[1]);
|
|
return point;
|
|
}
|
|
|
|
static TSInputEdit unmarshal_edit() {
|
|
TSInputEdit edit;
|
|
const void **address = TRANSFER_BUFFER;
|
|
edit.start_point = unmarshal_point(address); address += 2;
|
|
edit.old_end_point = unmarshal_point(address); address += 2;
|
|
edit.new_end_point = unmarshal_point(address); address += 2;
|
|
edit.start_byte = code_unit_to_byte((uint32_t)*address); address += 1;
|
|
edit.old_end_byte = code_unit_to_byte((uint32_t)*address); address += 1;
|
|
edit.new_end_byte = code_unit_to_byte((uint32_t)*address); address += 1;
|
|
return edit;
|
|
}
|
|
|
|
/********************/
|
|
/* Section - Parser */
|
|
/********************/
|
|
|
|
extern void tree_sitter_parse_callback(
|
|
char *input_buffer,
|
|
uint32_t index,
|
|
uint32_t row,
|
|
uint32_t column,
|
|
uint32_t *length_read
|
|
);
|
|
|
|
extern void tree_sitter_log_callback(
|
|
void *payload,
|
|
TSLogType log_type,
|
|
const char *message
|
|
);
|
|
|
|
void ts_parser_new_wasm() {
|
|
TSParser *parser = ts_parser_new();
|
|
char *input_buffer = calloc(INPUT_BUFFER_SIZE, sizeof(char));
|
|
TRANSFER_BUFFER[0] = parser;
|
|
TRANSFER_BUFFER[1] = input_buffer;
|
|
}
|
|
|
|
static const char *call_parse_callback(
|
|
void *payload,
|
|
uint32_t byte,
|
|
TSPoint position,
|
|
uint32_t *bytes_read
|
|
) {
|
|
char *buffer = (char *)payload;
|
|
tree_sitter_parse_callback(
|
|
buffer,
|
|
byte_to_code_unit(byte),
|
|
position.row,
|
|
byte_to_code_unit(position.column),
|
|
bytes_read
|
|
);
|
|
*bytes_read = code_unit_to_byte(*bytes_read);
|
|
if (*bytes_read > INPUT_BUFFER_SIZE) *bytes_read = INPUT_BUFFER_SIZE;
|
|
if (*bytes_read > 0) *bytes_read -= 2; // Remove null character
|
|
return buffer;
|
|
}
|
|
|
|
void ts_parser_enable_logger_wasm(TSParser *self, bool should_log) {
|
|
TSLogger logger = {self, should_log ? tree_sitter_log_callback : NULL};
|
|
ts_parser_set_logger(self, logger);
|
|
}
|
|
|
|
TSTree *ts_parser_parse_wasm(
|
|
TSParser *self,
|
|
char *input_buffer,
|
|
const TSTree *old_tree
|
|
) {
|
|
TSInput input = {
|
|
input_buffer,
|
|
call_parse_callback,
|
|
TSInputEncodingUTF16
|
|
};
|
|
return ts_parser_parse(self, old_tree, input);
|
|
}
|
|
|
|
/******************/
|
|
/* Section - Tree */
|
|
/******************/
|
|
|
|
void ts_tree_root_node_wasm(const TSTree *tree) {
|
|
marshal_node(ts_tree_root_node(tree));
|
|
}
|
|
|
|
void ts_tree_edit_wasm(TSTree *tree) {
|
|
TSInputEdit edit = unmarshal_edit();
|
|
ts_tree_edit(tree, &edit);
|
|
}
|
|
|
|
/******************/
|
|
/* Section - Node */
|
|
/******************/
|
|
|
|
uint16_t ts_node_symbol_wasm(const TSTree *tree) {
|
|
TSNode node = unmarshal_node(tree);
|
|
return ts_node_symbol(node);
|
|
}
|
|
|
|
uint32_t ts_node_child_count_wasm(const TSTree *tree) {
|
|
TSNode node = unmarshal_node(tree);
|
|
return ts_node_child_count(node);
|
|
}
|
|
|
|
uint32_t ts_node_named_child_count_wasm(const TSTree *tree) {
|
|
TSNode node = unmarshal_node(tree);
|
|
return ts_node_named_child_count(node);
|
|
}
|
|
|
|
void ts_node_child_wasm(const TSTree *tree, uint32_t index) {
|
|
TSNode node = unmarshal_node(tree);
|
|
marshal_node(ts_node_child(node, index));
|
|
}
|
|
|
|
void ts_node_named_child_wasm(const TSTree *tree, uint32_t index) {
|
|
TSNode node = unmarshal_node(tree);
|
|
marshal_node(ts_node_named_child(node, index));
|
|
}
|
|
|
|
void ts_node_parent_wasm(const TSTree *tree) {
|
|
TSNode node = unmarshal_node(tree);
|
|
marshal_node(ts_node_parent(node));
|
|
}
|
|
|
|
void ts_node_descendant_for_position_wasm(const TSTree *tree) {
|
|
TSNode node = unmarshal_node(tree);
|
|
const void **address = TRANSFER_BUFFER + 5;
|
|
TSPoint start = unmarshal_point(address); address += 2;
|
|
TSPoint end = unmarshal_point(address);
|
|
marshal_node(ts_node_descendant_for_point_range(node, start, end));
|
|
}
|
|
|
|
void ts_node_named_descendant_for_position_wasm(const TSTree *tree) {
|
|
TSNode node = unmarshal_node(tree);
|
|
const void **address = TRANSFER_BUFFER + 5;
|
|
TSPoint start = unmarshal_point(address); address += 2;
|
|
TSPoint end = unmarshal_point(address);
|
|
marshal_node(ts_node_named_descendant_for_point_range(node, start, end));
|
|
}
|
|
|
|
void ts_node_start_point_wasm(const TSTree *tree) {
|
|
TSNode node = unmarshal_node(tree);
|
|
marshal_point(ts_node_start_point(node));
|
|
}
|
|
|
|
void ts_node_end_point_wasm(const TSTree *tree) {
|
|
TSNode node = unmarshal_node(tree);
|
|
marshal_point(ts_node_end_point(node));
|
|
}
|
|
|
|
uint32_t ts_node_start_index_wasm(const TSTree *tree) {
|
|
TSNode node = unmarshal_node(tree);
|
|
return byte_to_code_unit(ts_node_start_byte(node));
|
|
}
|
|
|
|
uint32_t ts_node_end_index_wasm(const TSTree *tree) {
|
|
TSNode node = unmarshal_node(tree);
|
|
return byte_to_code_unit(ts_node_end_byte(node));
|
|
}
|
|
|
|
char *ts_node_to_string_wasm(const TSTree *tree) {
|
|
TSNode node = unmarshal_node(tree);
|
|
return ts_node_string(node);
|
|
}
|