From d2bf88d5fe0749f3fff67b75bef47dd0027d1caf Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 4 Dec 2015 20:20:29 -0800 Subject: [PATCH] Include rows and columns in TSLength This way, we don't have to have separate 1D and 2D versions for so many values --- include/tree_sitter/parser.h | 6 +- spec/runtime/helpers/tree_helpers.cc | 5 +- spec/runtime/stack_spec.cc | 53 +++++++-------- spec/runtime/tree_spec.cc | 84 +++++++++++------------- src/runtime/document.c | 2 +- src/runtime/length.h | 97 ++++++++++++---------------- src/runtime/lexer.c | 40 ++++-------- src/runtime/lexer.h | 2 +- src/runtime/node.c | 16 +++-- src/runtime/parser.c | 10 +-- src/runtime/stack.c | 7 +- src/runtime/stack.h | 1 - src/runtime/tree.c | 72 +++++++-------------- src/runtime/tree.h | 32 +++++---- 14 files changed, 186 insertions(+), 241 deletions(-) diff --git a/include/tree_sitter/parser.h b/include/tree_sitter/parser.h index 7ec6af89..a97adf61 100644 --- a/include/tree_sitter/parser.h +++ b/include/tree_sitter/parser.h @@ -19,6 +19,8 @@ typedef unsigned short TSStateId; typedef struct { size_t bytes; size_t chars; + size_t rows; + size_t columns; } TSLength; typedef struct { @@ -42,10 +44,6 @@ typedef struct TSLexer { TSLength token_end_position; TSLength token_start_position; - TSPoint current_point; - TSPoint token_end_point; - TSPoint token_start_point; - size_t lookahead_size; int32_t lookahead; diff --git a/spec/runtime/helpers/tree_helpers.cc b/spec/runtime/helpers/tree_helpers.cc index bdcb6e14..0bb734a2 100644 --- a/spec/runtime/helpers/tree_helpers.cc +++ b/spec/runtime/helpers/tree_helpers.cc @@ -1,4 +1,5 @@ #include "runtime/helpers/tree_helpers.h" +#include using std::string; using std::to_string; @@ -32,6 +33,6 @@ bool operator==(const TSNode &left, const TSNode &right) { } ostream &operator<<(ostream &stream, const TSLength &length) { - return stream << string("{") << to_string(length.chars) << string(", ") << - to_string(length.bytes) << string("}"); + return stream << "{chars:" << length.chars << ", bytes:" << + length.bytes << ", rows:" << length.rows << ", columns:" << length.columns << "}"; } diff --git a/spec/runtime/stack_spec.cc b/spec/runtime/stack_spec.cc index 0ec66991..db075700 100644 --- a/spec/runtime/stack_spec.cc +++ b/spec/runtime/stack_spec.cc @@ -19,11 +19,7 @@ struct TreeSelectionSpy { }; TSLength operator*(const TSLength &length, size_t factor) { - return {length.bytes * factor, length.chars * factor}; -} - -TSPoint operator*(const TSPoint &point, size_t factor) { - return {0, point.column * factor}; + return {length.bytes * factor, length.chars * factor, 0, length.columns * factor}; } extern "C" @@ -43,8 +39,7 @@ describe("Stack", [&]() { const size_t tree_count = 10; TSTree *trees[tree_count]; TreeSelectionSpy tree_selection_spy{0, NULL, {NULL, NULL}}; - TSLength tree_len = ts_length_make(2, 3); - TSPoint tree_extent = ts_point_make(0, 3); + TSLength tree_len = {2, 3, 0, 3}; TSSymbolMetadata metadata = {true, true, true}; before_each([&]() { @@ -54,7 +49,7 @@ describe("Stack", [&]() { }); for (size_t i = 0; i < tree_count; i++) - trees[i] = ts_tree_make_leaf(i, ts_length_zero(), tree_len, ts_point_zero(), tree_extent, {}); + trees[i] = ts_tree_make_leaf(i, ts_length_zero(), tree_len, {}); }); after_each([&]() { @@ -73,7 +68,7 @@ describe("Stack", [&]() { */ ts_stack_push(stack, 0, stateA, trees[0]); const StackEntry *entry1 = ts_stack_head(stack, 0); - AssertThat(*entry1, Equals({trees[0], stateA, tree_len, tree_extent})); + AssertThat(*entry1, Equals({trees[0], stateA, tree_len})); AssertThat(ts_stack_entry_next_count(entry1), Equals(1)); AssertThat(ts_stack_entry_next(entry1, 0), Equals(nullptr)); @@ -82,7 +77,7 @@ describe("Stack", [&]() { */ ts_stack_push(stack, 0, stateB, trees[1]); const StackEntry *entry2 = ts_stack_head(stack, 0); - AssertThat(*entry2, Equals({trees[1], stateB, tree_len * 2, tree_extent * 2})); + AssertThat(*entry2, Equals({trees[1], stateB, tree_len * 2})); AssertThat(ts_stack_entry_next_count(entry2), Equals(1)); AssertThat(ts_stack_entry_next(entry2, 0), Equals(entry1)); @@ -91,7 +86,7 @@ describe("Stack", [&]() { */ ts_stack_push(stack, 0, stateC, trees[2]); const StackEntry *entry3 = ts_stack_head(stack, 0); - AssertThat(*entry3, Equals({trees[2], stateC, tree_len * 3, tree_extent * 2})); + AssertThat(*entry3, Equals({trees[2], stateC, tree_len * 3})); AssertThat(ts_stack_entry_next_count(entry3), Equals(1)); AssertThat(ts_stack_entry_next(entry3, 0), Equals(entry2)); }); @@ -117,7 +112,7 @@ describe("Stack", [&]() { AssertThat(pop1.tree_count, Equals(2)); AssertThat(pop1.trees[0], Equals(trees[1])); AssertThat(pop1.trees[1], Equals(trees[2])); - AssertThat(*ts_stack_head(stack, 0), Equals({trees[0], stateA, tree_len, tree_extent})); + AssertThat(*ts_stack_head(stack, 0), Equals({trees[0], stateA, tree_len})); /* * . @@ -176,8 +171,8 @@ describe("Stack", [&]() { ts_stack_pop(stack, 1, 1, false); AssertThat(ts_stack_head_count(stack), Equals(2)); - AssertThat(*ts_stack_head(stack, 0), Equals({trees[3], stateD, tree_len * 4, tree_extent * 4})); - AssertThat(*ts_stack_head(stack, 1), Equals({trees[1], stateB, tree_len * 2, tree_extent * 2})); + AssertThat(*ts_stack_head(stack, 0), Equals({trees[3], stateD, tree_len * 4})); + AssertThat(*ts_stack_head(stack, 1), Equals({trees[1], stateB, tree_len * 2})); /* * A0__B1__C2__D3. @@ -187,8 +182,8 @@ describe("Stack", [&]() { ts_stack_push(stack, 1, stateF, trees[3]); AssertThat(ts_stack_head_count(stack), Equals(2)); - AssertThat(*ts_stack_head(stack, 0), Equals({trees[3], stateD, tree_len * 4, tree_extent * 4})); - AssertThat(*ts_stack_head(stack, 1), Equals({trees[3], stateF, tree_len * 4, tree_extent * 4})); + AssertThat(*ts_stack_head(stack, 0), Equals({trees[3], stateD, tree_len * 4})); + AssertThat(*ts_stack_head(stack, 1), Equals({trees[3], stateF, tree_len * 4})); }); }); @@ -207,8 +202,8 @@ describe("Stack", [&]() { ts_stack_push(stack, 1, stateF, trees[5]); AssertThat(ts_stack_head_count(stack), Equals(2)); - AssertThat(*ts_stack_head(stack, 0), Equals({trees[3], stateD, tree_len * 4, tree_extent * 4})); - AssertThat(*ts_stack_head(stack, 1), Equals({trees[5], stateF, tree_len * 4, tree_extent * 4})); + AssertThat(*ts_stack_head(stack, 0), Equals({trees[3], stateD, tree_len * 4})); + AssertThat(*ts_stack_head(stack, 1), Equals({trees[5], stateF, tree_len * 4})); }); describe("when the trees are identical", [&]() { @@ -224,10 +219,10 @@ describe("Stack", [&]() { AssertThat(ts_stack_head_count(stack), Equals(1)); const StackEntry *entry1 = ts_stack_head(stack, 0); - AssertThat(*entry1, Equals({trees[6], stateG, tree_len * 5, tree_extent * 5})); + AssertThat(*entry1, Equals({trees[6], stateG, tree_len * 5})); AssertThat(ts_stack_entry_next_count(entry1), Equals(2)); - AssertThat(*ts_stack_entry_next(entry1, 0), Equals({trees[3], stateD, tree_len * 4, tree_extent * 4})); - AssertThat(*ts_stack_entry_next(entry1, 1), Equals({trees[5], stateF, tree_len * 4, tree_extent * 4})); + AssertThat(*ts_stack_entry_next(entry1, 0), Equals({trees[3], stateD, tree_len * 4})); + AssertThat(*ts_stack_entry_next(entry1, 1), Equals({trees[5], stateF, tree_len * 4})); }); }); @@ -251,7 +246,7 @@ describe("Stack", [&]() { AssertThat(tree_selection_spy.call_count, Equals(1)); AssertThat(tree_selection_spy.arguments[0], Equals(trees[6])); AssertThat(tree_selection_spy.arguments[1], Equals(trees[7])); - AssertThat(*ts_stack_head(stack, 0), Equals({trees[7], stateG, tree_len * 5, tree_extent * 5})); + AssertThat(*ts_stack_head(stack, 0), Equals({trees[7], stateG, tree_len * 5})); }); }); @@ -277,11 +272,11 @@ describe("Stack", [&]() { AssertThat(ts_stack_head_count(stack), Equals(1)); StackEntry *head = ts_stack_head(stack, 0); - AssertThat(*head, Equals({trees[7], stateH, tree_len * 6, tree_extent * 6})) + AssertThat(*head, Equals({trees[7], stateH, tree_len * 6})) AssertThat(ts_stack_entry_next_count(head), Equals(1)); StackEntry *next = ts_stack_entry_next(head, 0); - AssertThat(*next, Equals({trees[6], stateG, tree_len * 5, tree_extent * 5})) + AssertThat(*next, Equals({trees[6], stateG, tree_len * 5})) AssertThat(ts_stack_entry_next_count(next), Equals(2)); }); }); @@ -309,11 +304,11 @@ describe("Stack", [&]() { AssertThat(ts_stack_head_count(stack), Equals(1)); StackEntry *head = ts_stack_head(stack, 0); - AssertThat(*head, Equals({parent, stateC, tree_len * 2, tree_extent * 2})); + AssertThat(*head, Equals({parent, stateC, tree_len * 2})); AssertThat(ts_stack_entry_next_count(head), Equals(2)); AssertThat(ts_stack_entry_next(head, 0), Equals(nullptr)); - AssertThat(*ts_stack_entry_next(head, 1), Equals({trees[2], stateB, tree_len, tree_extent})); + AssertThat(*ts_stack_entry_next(head, 1), Equals({trees[2], stateB, tree_len})); }); }); }); @@ -360,8 +355,8 @@ describe("Stack", [&]() { AssertThat(pop2.trees[1], Equals(trees[6])); AssertThat(ts_stack_head_count(stack), Equals(2)); - AssertThat(*ts_stack_head(stack, 0), Equals({trees[2], stateC, tree_len * 3, tree_extent * 3})); - AssertThat(*ts_stack_head(stack, 1), Equals({trees[4], stateE, tree_len * 3, tree_extent * 3})); + AssertThat(*ts_stack_head(stack, 0), Equals({trees[2], stateC, tree_len * 3})); + AssertThat(*ts_stack_head(stack, 1), Equals({trees[4], stateE, tree_len * 3})); }); }); @@ -424,7 +419,7 @@ describe("Stack", [&]() { */ Vector pop = ts_stack_pop(stack, 0, 3, false); AssertThat(ts_stack_head_count(stack), Equals(1)); - AssertThat(*ts_stack_head(stack, 0), Equals({trees[1], stateB, tree_len * 2, tree_extent * 2})); + AssertThat(*ts_stack_head(stack, 0), Equals({trees[1], stateB, tree_len * 2})); AssertThat(pop.size, Equals(2)); StackPopResult pop1 = *(StackPopResult *)vector_get(&pop, 0); diff --git a/spec/runtime/tree_spec.cc b/spec/runtime/tree_spec.cc index 7067f418..53e14950 100644 --- a/spec/runtime/tree_spec.cc +++ b/spec/runtime/tree_spec.cc @@ -31,8 +31,8 @@ describe("Tree", []() { TSSymbolMetadata invisible = {false, false, false}; before_each([&]() { - tree1 = ts_tree_make_leaf(cat, {2, 1}, {5, 4}, ts_point_zero(), ts_point_zero(), visible); - tree2 = ts_tree_make_leaf(cat, {1, 1}, {3, 3}, ts_point_zero(), ts_point_zero(), visible); + tree1 = ts_tree_make_leaf(cat, {2, 1, 0, 1}, {5, 4, 0, 4}, visible); + tree2 = ts_tree_make_leaf(cat, {1, 1, 0, 1}, {3, 3, 0, 3}, visible); parent1 = ts_tree_make_node(dog, 2, tree_array({ tree1, tree2, @@ -57,8 +57,6 @@ describe("Tree", []() { TSTree *error_tree = ts_tree_make_error( ts_length_zero(), ts_length_zero(), - ts_point_zero(), - ts_point_zero(), 'z'); AssertThat(ts_tree_is_fragile_left(error_tree), IsTrue()); @@ -149,13 +147,13 @@ describe("Tree", []() { before_each([&]() { tree = ts_tree_make_node(cat, 3, tree_array({ - ts_tree_make_leaf(dog, {2, 2}, {3, 3}, {1, 2}, {1, 3}, visible), - ts_tree_make_leaf(eel, {2, 2}, {3, 3}, {1, 2}, {1, 3}, visible), - ts_tree_make_leaf(fox, {2, 2}, {3, 3}, {1, 2}, {1, 3}, visible), + ts_tree_make_leaf(dog, {2, 2, 0, 2}, {3, 3, 0, 3}, visible), + ts_tree_make_leaf(eel, {2, 2, 0, 2}, {3, 3, 0, 3}, visible), + ts_tree_make_leaf(fox, {2, 2, 0, 2}, {3, 3, 0, 3}, visible), }), visible); - AssertThat(tree->padding, Equals({2, 2})); - AssertThat(tree->size, Equals({13, 13})); + AssertThat(tree->padding, Equals({2, 2, 0, 2})); + AssertThat(tree->size, Equals({13, 13, 0, 13})); }); after_each([&]() { @@ -178,16 +176,16 @@ describe("Tree", []() { assert_consistent(tree); AssertThat(tree->options.has_changes, IsTrue()); - AssertThat(tree->padding, Equals({0, 3})); - AssertThat(tree->size, Equals({13, 13})); + AssertThat(tree->padding, Equals({0, 3, 0, 0})); + AssertThat(tree->size, Equals({13, 13, 0, 13})); AssertThat(tree->children[0]->options.has_changes, IsTrue()); - AssertThat(tree->children[0]->padding, Equals({0, 3})); - AssertThat(tree->children[0]->size, Equals({3, 3})); + AssertThat(tree->children[0]->padding, Equals({0, 3, 0, 0})); + AssertThat(tree->children[0]->size, Equals({3, 3, 0, 3})); AssertThat(tree->children[1]->options.has_changes, IsFalse()); - AssertThat(tree->children[1]->padding, Equals({2, 2})); - AssertThat(tree->children[1]->size, Equals({3, 3})); + AssertThat(tree->children[1]->padding, Equals({2, 2, 0, 2})); + AssertThat(tree->children[1]->size, Equals({3, 3, 0, 3})); }); }); @@ -198,12 +196,12 @@ describe("Tree", []() { assert_consistent(tree); AssertThat(tree->options.has_changes, IsTrue()); - AssertThat(tree->padding, Equals({0, 5})); - AssertThat(tree->size, Equals({0, 11})); + AssertThat(tree->padding, Equals({0, 5, 0, 0})); + AssertThat(tree->size, Equals({0, 11, 0, 0})); AssertThat(tree->children[0]->options.has_changes, IsTrue()); - AssertThat(tree->children[0]->padding, Equals({0, 5})); - AssertThat(tree->children[0]->size, Equals({0, 1})); + AssertThat(tree->children[0]->padding, Equals({0, 5, 0, 0})); + AssertThat(tree->children[0]->size, Equals({0, 1, 0, 0})); }); }); @@ -214,12 +212,12 @@ describe("Tree", []() { assert_consistent(tree); AssertThat(tree->options.has_changes, IsTrue()); - AssertThat(tree->padding, Equals({0, 4})); - AssertThat(tree->size, Equals({13, 13})); + AssertThat(tree->padding, Equals({0, 4, 0, 0})); + AssertThat(tree->size, Equals({13, 13, 0, 13})); AssertThat(tree->children[0]->options.has_changes, IsTrue()); - AssertThat(tree->children[0]->padding, Equals({0, 4})); - AssertThat(tree->children[0]->size, Equals({3, 3})); + AssertThat(tree->children[0]->padding, Equals({0, 4, 0, 0})); + AssertThat(tree->children[0]->size, Equals({3, 3, 0, 3})); AssertThat(tree->children[1]->options.has_changes, IsFalse()); }); @@ -232,12 +230,12 @@ describe("Tree", []() { assert_consistent(tree); AssertThat(tree->options.has_changes, IsTrue()); - AssertThat(tree->padding, Equals({2, 2})); - AssertThat(tree->size, Equals({0, 16})); + AssertThat(tree->padding, Equals({2, 2, 0, 2})); + AssertThat(tree->size, Equals({0, 16, 0, 0})); AssertThat(tree->children[0]->options.has_changes, IsTrue()); - AssertThat(tree->children[0]->padding, Equals({2, 2})); - AssertThat(tree->children[0]->size, Equals({0, 6})); + AssertThat(tree->children[0]->padding, Equals({2, 2, 0, 2})); + AssertThat(tree->children[0]->size, Equals({0, 6, 0, 0})); AssertThat(tree->children[1]->options.has_changes, IsFalse()); }); @@ -250,30 +248,30 @@ describe("Tree", []() { assert_consistent(tree); AssertThat(tree->options.has_changes, IsTrue()); - AssertThat(tree->padding, Equals({0, 4})); - AssertThat(tree->size, Equals({0, 4})); + AssertThat(tree->padding, Equals({0, 4, 0, 0})); + AssertThat(tree->size, Equals({0, 4, 0, 0})); AssertThat(tree->children[0]->options.has_changes, IsTrue()); - AssertThat(tree->children[0]->padding, Equals({0, 4})); - AssertThat(tree->children[0]->size, Equals({0, 0})); + AssertThat(tree->children[0]->padding, Equals({0, 4, 0, 0})); + AssertThat(tree->children[0]->size, Equals({0, 0, 0, 0})); AssertThat(tree->children[1]->options.has_changes, IsTrue()); - AssertThat(tree->children[1]->padding, Equals({0, 0})); - AssertThat(tree->children[1]->size, Equals({0, 0})); + AssertThat(tree->children[1]->padding, Equals({0, 0, 0, 0})); + AssertThat(tree->children[1]->size, Equals({0, 0, 0, 0})); AssertThat(tree->children[2]->options.has_changes, IsTrue()); - AssertThat(tree->children[2]->padding, Equals({0, 1})); - AssertThat(tree->children[2]->size, Equals({3, 3})); + AssertThat(tree->children[2]->padding, Equals({0, 1, 0, 0})); + AssertThat(tree->children[2]->size, Equals({3, 3, 0, 3})); }); }); }); describe("equality", [&]() { it("returns true for identical trees", [&]() { - TSTree *tree1_copy = ts_tree_make_leaf(cat, {2, 1}, {5, 4}, {1, 1}, {1, 4}, visible); + TSTree *tree1_copy = ts_tree_make_leaf(cat, {2, 1, 1, 1}, {5, 4, 1, 4}, visible); AssertThat(ts_tree_eq(tree1, tree1_copy), IsTrue()); - TSTree *tree2_copy = ts_tree_make_leaf(cat, {1, 1}, {3, 3}, {1, 1}, {1, 3}, visible); + TSTree *tree2_copy = ts_tree_make_leaf(cat, {1, 1, 0, 1}, {3, 3, 0, 3}, visible); AssertThat(ts_tree_eq(tree2, tree2_copy), IsTrue()); TSTree *parent2 = ts_tree_make_node(dog, 2, tree_array({ @@ -293,8 +291,6 @@ describe("Tree", []() { tree1->symbol + 1, tree1->padding, tree1->size, - tree1->padding_point, - tree1->size_point, visible); AssertThat(ts_tree_eq(tree1, different_tree), IsFalse()); @@ -302,17 +298,17 @@ describe("Tree", []() { }); it("returns false for trees with different options", [&]() { - TSTree *tree1_copy = ts_tree_make_leaf(cat, tree1->padding, tree1->size, tree1->padding_point, tree1->size_point, invisible); + TSTree *tree1_copy = ts_tree_make_leaf(cat, tree1->padding, tree1->size, invisible); AssertThat(ts_tree_eq(tree1, tree1_copy), IsFalse()); ts_tree_release(tree1_copy); }); - it("returns false for trees with different 2D dimensions", [&]() { - TSTree *tree1_copy = ts_tree_make_leaf(cat, tree1->padding, tree1->size, {5, 10}, tree1->size_point, invisible); + it("returns false for trees with different sizes", [&]() { + TSTree *tree1_copy = ts_tree_make_leaf(cat, {2, 1, 0, 1}, tree1->size, invisible); AssertThat(ts_tree_eq(tree1, tree1_copy), IsFalse()); ts_tree_release(tree1_copy); - tree1_copy = ts_tree_make_leaf(cat, tree1->padding, tree1->size, tree1->padding_point, {5, 10}, invisible); + tree1_copy = ts_tree_make_leaf(cat, tree1->padding, {5, 4, 1, 10}, invisible); AssertThat(ts_tree_eq(tree1, tree1_copy), IsFalse()); ts_tree_release(tree1_copy); }); @@ -322,8 +318,6 @@ describe("Tree", []() { tree1->symbol + 1, tree1->padding, tree1->size, - tree1->padding_point, - tree1->size_point, visible); TSTree *different_parent = ts_tree_make_node(dog, 2, tree_array({ diff --git a/src/runtime/document.c b/src/runtime/document.c index 5f0aef85..9747f912 100644 --- a/src/runtime/document.c +++ b/src/runtime/document.c @@ -53,7 +53,7 @@ void ts_document_edit(TSDocument *self, TSInputEdit edit) { if (!self->tree) return; - size_t max_chars = ts_tree_total_size(self->tree).chars; + size_t max_chars = ts_tree_total_chars(self->tree); if (edit.position > max_chars) edit.position = max_chars; if (edit.chars_removed > max_chars - edit.position) diff --git a/src/runtime/length.h b/src/runtime/length.h index f9d91df0..82673fa6 100644 --- a/src/runtime/length.h +++ b/src/runtime/length.h @@ -4,82 +4,69 @@ #include "tree_sitter/parser.h" #include +static inline bool ts_length_is_unknown(TSLength self) { + return self.chars > 0 && self.bytes == 0; +} + +static inline void ts_length_set_unknown(TSLength *self) { + self->bytes = 0; + self->rows = 0; + self->columns = 0; +} + static inline TSLength ts_length_add(TSLength len1, TSLength len2) { TSLength result; - result.bytes = len1.bytes + len2.bytes; result.chars = len1.chars + len2.chars; - if ((len1.chars > 0 && len1.bytes == 0) || (len2.chars > 0 && len2.bytes == 0)) + if (ts_length_is_unknown(len1) || ts_length_is_unknown(len2)) { result.bytes = 0; + result.rows = 0; + result.columns = result.chars; + } else { + result.bytes = len1.bytes + len2.bytes; + if (len2.rows == 0) { + result.rows = len1.rows; + result.columns = len1.columns + len2.columns; + } else { + result.rows = len1.rows + len2.rows; + result.columns = len2.columns; + } + } return result; } static inline TSLength ts_length_sub(TSLength len1, TSLength len2) { TSLength result; - result.bytes = len1.bytes - len2.bytes; result.chars = len1.chars - len2.chars; - if ((len1.chars > 0 && len1.bytes == 0) || (len2.chars > 0 && len2.bytes == 0)) + if (ts_length_is_unknown(len1) || ts_length_is_unknown(len2)) { result.bytes = 0; + result.rows = 0; + result.columns = result.chars; + } else { + result.bytes = len1.bytes - len2.bytes; + if (len1.rows == len2.rows) { + result.rows = 0; + result.columns = len1.columns - len2.columns; + } else { + result.rows = len1.rows - len2.rows; + result.columns = len1.columns; + } + } return result; } -static inline TSPoint ts_point_make(size_t row, size_t column) { - TSPoint point; - point.row = row; - point.column = column; - return point; -} - -static inline TSPoint ts_point_add(TSPoint point1, TSPoint point2) { - size_t row = point1.row + point2.row; - - size_t column; - if (point2.row == 0) { - column = point1.column + point2.column; - } else { - column = point2.column; - } - - return ts_point_make(row, column); -} - -static inline TSPoint ts_point_sub(TSPoint point1, TSPoint point2) { - size_t row, column; - if (point1.row == point2.row) { - row = 0; - column = point1.column - point2.column; - } else { - row = point1.row - point2.row; - column = point1.column; - } - - return ts_point_make(row, column); -} - static inline TSLength ts_length_zero() { - TSLength result; - result.bytes = result.chars = 0; - return result; + return (TSLength){0, 0, 0, 0}; } -static inline bool ts_length_eq(TSLength len1, TSLength len2) { - return len1.bytes == len2.bytes && len1.chars == len2.chars; -} - -static inline TSPoint ts_point_zero() { - TSPoint point; - point.row = point.column = 0; - return point; -} - -static inline TSLength ts_length_make(size_t bytes, size_t chars) { - TSLength result; - result.bytes = bytes; - result.chars = chars; - return result; +static inline bool ts_length_eq(TSLength self, TSLength other) { + return self.bytes == other.bytes && + self.chars == other.chars && + self.rows == other.rows && + self.columns == other.columns; } #endif diff --git a/src/runtime/lexer.c b/src/runtime/lexer.c index b443082c..4536399e 100644 --- a/src/runtime/lexer.c +++ b/src/runtime/lexer.c @@ -51,10 +51,8 @@ static void ts_lexer__start(TSLexer *self, TSStateId lex_state) { } static void ts_lexer__start_token(TSLexer *self) { - LOG("start_token chars:%lu, rows:%lu, columns:%lu", self->current_position.chars, self->current_point.row, self->current_point.column); - + LOG("start_token chars:%lu, rows:%lu, columns:%lu", self->current_position.chars, self->current_position.rows, self->current_position.columns); self->token_start_position = self->current_position; - self->token_start_point = self->current_point; } static bool ts_lexer__advance(TSLexer *self, TSStateId state) { @@ -65,13 +63,13 @@ static bool ts_lexer__advance(TSLexer *self, TSStateId state) { if (self->lookahead_size) { self->current_position.bytes += self->lookahead_size; - self->current_position.chars += 1; + self->current_position.chars++; if (self->lookahead == '\n') { - self->current_point.row += 1; - self->current_point.column = 0; + self->current_position.rows++; + self->current_position.columns = 0; } else { - self->current_point.column += 1; + self->current_position.columns++; } } @@ -85,22 +83,16 @@ static bool ts_lexer__advance(TSLexer *self, TSStateId state) { static TSTree *ts_lexer__accept(TSLexer *self, TSSymbol symbol, TSSymbolMetadata metadata, const char *symbol_name) { - TSLength size = - ts_length_sub(self->current_position, self->token_start_position); - TSLength padding = - ts_length_sub(self->token_start_position, self->token_end_position); + TSLength size = ts_length_sub(self->current_position, self->token_start_position); + TSLength padding = ts_length_sub(self->token_start_position, self->token_end_position); self->token_end_position = self->current_position; - TSPoint size_point = ts_point_sub(self->current_point, self ->token_start_point); - TSPoint padding_point = ts_point_sub(self->token_start_point, self->token_end_point); - self->token_end_point = self->current_point; - if (symbol == ts_builtin_sym_error) { LOG("error_char"); - return ts_tree_make_error(size, padding, size_point, padding_point, self->lookahead); + return ts_tree_make_error(size, padding, self->lookahead); } else { LOG("accept_token sym:%s", symbol_name); - return ts_tree_make_leaf(symbol, padding, size, padding_point, size_point, metadata); + return ts_tree_make_leaf(symbol, padding, size, metadata); } } @@ -119,19 +111,15 @@ TSLexer ts_lexer_make() { .chunk_start = 0, .debugger = ts_debugger_null(), }; - ts_lexer_reset(&result, ts_length_zero(), ts_point_zero()); + ts_lexer_reset(&result, ts_length_zero()); return result; } -static inline void ts_lexer__reset(TSLexer *self, TSLength position, TSPoint point) { +static inline void ts_lexer__reset(TSLexer *self, TSLength position) { self->token_start_position = position; self->token_end_position = position; self->current_position = position; - self->token_start_point = point; - self->token_end_point = point; - self->current_point = point; - self->chunk = 0; self->chunk_start = 0; self->chunk_size = 0; @@ -141,11 +129,11 @@ static inline void ts_lexer__reset(TSLexer *self, TSLength position, TSPoint poi void ts_lexer_set_input(TSLexer *self, TSInput input) { self->input = input; - ts_lexer__reset(self, ts_length_zero(), ts_point_zero()); + ts_lexer__reset(self, ts_length_zero()); } -void ts_lexer_reset(TSLexer *self, TSLength position, TSPoint point) { +void ts_lexer_reset(TSLexer *self, TSLength position) { if (!ts_length_eq(position, self->current_position)) - ts_lexer__reset(self, position, point); + ts_lexer__reset(self, position); return; } diff --git a/src/runtime/lexer.h b/src/runtime/lexer.h index 3dfe4ff5..c5957421 100644 --- a/src/runtime/lexer.h +++ b/src/runtime/lexer.h @@ -9,7 +9,7 @@ extern "C" { TSLexer ts_lexer_make(); void ts_lexer_set_input(TSLexer *, TSInput); -void ts_lexer_reset(TSLexer *, TSLength, TSPoint); +void ts_lexer_reset(TSLexer *, TSLength); #ifdef __cplusplus } diff --git a/src/runtime/node.c b/src/runtime/node.c index e80b6b83..4aa76f23 100644 --- a/src/runtime/node.c +++ b/src/runtime/node.c @@ -1,6 +1,5 @@ #include #include "runtime/node.h" -#include "runtime/length.h" #include "runtime/tree.h" #include "runtime/document.h" @@ -49,7 +48,7 @@ static inline TSNode ts_node__direct_parent(TSNode self, size_t *index) { tree->context.parent, ts_node__offset_char(self) - tree->context.offset.chars, ts_node__offset_byte(self) - tree->context.offset.bytes, - ts_node__offset_row(self) - tree->context.offset_point.row + ts_node__offset_row(self) - tree->context.offset.rows ); } @@ -59,7 +58,7 @@ static inline TSNode ts_node__direct_child(TSNode self, size_t i) { child_tree, ts_node__offset_char(self) + child_tree->context.offset.chars, ts_node__offset_byte(self) + child_tree->context.offset.bytes, - ts_node__offset_row(self) + child_tree->context.offset_point.row + ts_node__offset_row(self) + child_tree->context.offset.rows ); } @@ -189,11 +188,18 @@ size_t ts_node_end_byte(TSNode self) { TSPoint ts_node_start_point(TSNode self) { const TSTree *tree = ts_node__tree(self); - return ts_point_make(ts_node__offset_row(self) + tree->padding_point.row, ts_tree_offset_column(tree)); + return (TSPoint){ + ts_node__offset_row(self) + tree->padding.rows, + ts_tree_start_column(tree) + }; } TSPoint ts_node_end_point(TSNode self) { - return ts_point_add(ts_node_start_point(self), ts_node__tree(self)->size_point); + const TSTree *tree = ts_node__tree(self); + return (TSPoint){ + ts_node__offset_row(self) + tree->padding.rows + tree->size.rows, + ts_tree_end_column(tree) + }; } TSSymbol ts_node_symbol(TSNode self) { diff --git a/src/runtime/parser.c b/src/runtime/parser.c index 447a97ef..747a6dc6 100644 --- a/src/runtime/parser.c +++ b/src/runtime/parser.c @@ -58,8 +58,7 @@ static bool ts_parser__breakdown_reusable_subtree(LookaheadState *state) { * NULL if no right neighbor exists. */ static void ts_parser__pop_reusable_subtree(LookaheadState *state) { - state->reusable_subtree_pos += - ts_tree_total_size(state->reusable_subtree).chars; + state->reusable_subtree_pos += ts_tree_total_chars(state->reusable_subtree); while (state->reusable_subtree) { TSTree *parent = state->reusable_subtree->context.parent; @@ -304,10 +303,8 @@ static void ts_parser__reduce_error(TSParser *self, int head, TSTree **parent = vector_back(&self->reduce_parents); StackEntry *stack_entry = ts_stack_head(self->stack, head); stack_entry->position = ts_length_add(stack_entry->position, lookahead->padding); - stack_entry->position_point = ts_point_add(stack_entry->position_point, lookahead->padding_point); (*parent)->size = ts_length_add((*parent)->size, lookahead->padding); lookahead->padding = ts_length_zero(); - lookahead->padding_point = ts_point_zero(); ts_tree_set_fragile_left(*parent); ts_tree_set_fragile_right(*parent); } @@ -546,7 +543,6 @@ TSTree *ts_parser_parse(TSParser *self, TSInput input, TSTree *previous_tree) { for (int head = 0; head < ts_stack_head_count(self->stack);) { StackEntry *entry = ts_stack_head(self->stack, head); TSLength position = entry ? entry->position : ts_length_zero(); - TSPoint position_point = entry ? entry->position_point : ts_point_zero(); LOG("process head:%d, head_count:%d, state:%d, pos:%lu", head, ts_stack_head_count(self->stack), @@ -559,7 +555,7 @@ TSTree *ts_parser_parse(TSParser *self, TSInput input, TSTree *previous_tree) { lookahead = reused_lookahead; } else { last_position = position; - ts_lexer_reset(&self->lexer, position, position_point); + ts_lexer_reset(&self->lexer, position); TSStateId parse_state = ts_stack_top_state(self->stack, head); TSStateId lex_state = self->language->lex_states[parse_state]; lookahead = self->language->lex_fn(&self->lexer, lex_state); @@ -567,7 +563,7 @@ TSTree *ts_parser_parse(TSParser *self, TSInput input, TSTree *previous_tree) { } LOG("lookahead sym:%s, size:%lu", SYM_NAME(lookahead->symbol), - ts_tree_total_size(lookahead).chars); + ts_tree_total_chars(lookahead)); switch (ts_parser__consume_lookahead(self, head, lookahead)) { case ConsumeResultRemoved: diff --git a/src/runtime/stack.c b/src/runtime/stack.c index 7530da7c..43fcb24f 100644 --- a/src/runtime/stack.c +++ b/src/runtime/stack.c @@ -126,18 +126,15 @@ static StackNode *stack_node_new(StackNode *next, TSStateId state, TSTree *tree) ts_tree_retain(tree); stack_node_retain(next); TSLength position = ts_tree_total_size(tree); - TSPoint position_point = ts_tree_total_size_point(tree); - if (next) { + if (next) position = ts_length_add(next->entry.position, position); - position_point = ts_point_add(next->entry.position_point, position_point); - } *self = (StackNode){ .ref_count = 1, .successor_count = 1, .successors = { next, NULL, NULL }, .entry = { - .state = state, .tree = tree, .position = position, .position_point = position_point, + .state = state, .tree = tree, .position = position }, }; return self; diff --git a/src/runtime/stack.h b/src/runtime/stack.h index b2f8969b..6c37864e 100644 --- a/src/runtime/stack.h +++ b/src/runtime/stack.h @@ -14,7 +14,6 @@ typedef struct { TSTree *tree; TSStateId state; TSLength position; - TSPoint position_point; } StackEntry; typedef struct { diff --git a/src/runtime/tree.c b/src/runtime/tree.c index 2e2a5d89..47be36ee 100644 --- a/src/runtime/tree.c +++ b/src/runtime/tree.c @@ -7,8 +7,6 @@ #include "runtime/length.h" TSTree *ts_tree_make_leaf(TSSymbol sym, TSLength padding, TSLength size, - TSPoint padding_point, - TSPoint size_point, TSSymbolMetadata metadata) { TSTree *result = malloc(sizeof(TSTree)); *result = (TSTree){ @@ -20,8 +18,6 @@ TSTree *ts_tree_make_leaf(TSSymbol sym, TSLength padding, TSLength size, .named_child_count = 0, .children = NULL, .padding = padding, - .padding_point = padding_point, - .size_point = size_point, .options = { .visible = metadata.visible, .named = metadata.named, @@ -36,33 +32,26 @@ TSTree *ts_tree_make_leaf(TSSymbol sym, TSLength padding, TSLength size, return result; } -TSTree *ts_tree_make_error(TSLength size, TSLength padding, - TSPoint size_point, - TSPoint padding_point, - char lookahead_char) { +TSTree *ts_tree_make_error(TSLength size, TSLength padding, char lookahead_char) { TSTree *result = - ts_tree_make_leaf(ts_builtin_sym_error, padding, size, padding_point, - size_point, (TSSymbolMetadata){ - .visible = true, .named = true, - }); + ts_tree_make_leaf(ts_builtin_sym_error, padding, size, (TSSymbolMetadata){ + .visible = true, .named = true, + }); result->lookahead_char = lookahead_char; return result; } void ts_tree_assign_parents(TSTree *self) { TSLength offset = ts_length_zero(); - TSPoint offset_point = ts_point_zero(); for (size_t i = 0; i < self->child_count; i++) { TSTree *child = self->children[i]; if (child->context.parent != self) { child->context.parent = self; child->context.index = i; child->context.offset = offset; - child->context.offset_point = offset_point; ts_tree_assign_parents(child); } offset = ts_length_add(offset, ts_tree_total_size(child)); - offset_point = ts_point_add(offset_point, ts_tree_total_size_point(child)); } } @@ -77,12 +66,8 @@ void ts_tree_set_children(TSTree *self, size_t child_count, TSTree **children) { if (i == 0) { self->padding = child->padding; self->size = child->size; - self->padding_point = child->padding_point; - self->size_point = child->size_point; } else { - self->size = - ts_length_add(ts_length_add(self->size, child->padding), child->size); - self->size_point = ts_point_add(ts_point_add(self->size_point, child->padding_point), child->size_point); + self->size = ts_length_add(self->size, ts_tree_total_size(child)); } if (child->options.visible) { @@ -106,7 +91,7 @@ void ts_tree_set_children(TSTree *self, size_t child_count, TSTree **children) { TSTree *ts_tree_make_node(TSSymbol symbol, size_t child_count, TSTree **children, TSSymbolMetadata metadata) { TSTree *result = - ts_tree_make_leaf(symbol, ts_length_zero(), ts_length_zero(), ts_point_zero(), ts_point_zero(), metadata); + ts_tree_make_leaf(symbol, ts_length_zero(), ts_length_zero(), metadata); ts_tree_set_children(result, child_count, children); return result; } @@ -128,32 +113,23 @@ void ts_tree_release(TSTree *self) { } } -size_t ts_tree_offset_column(const TSTree *self) { - size_t column = self->padding_point.column; - - if (self->padding_point.row > 0) { +size_t ts_tree_start_column(const TSTree *self) { + size_t column = self->padding.columns; + if (self->padding.rows > 0) return column; + for (const TSTree *tree = self; tree != NULL; tree = tree->context.parent) { + column += tree->context.offset.columns; + if (tree->context.offset.rows > 0) + break; } - - const TSTree *parent = self; - TSPoint offset_point; - do { - offset_point = parent->context.offset_point; - column += offset_point.column; - - parent = parent->context.parent; - if (!parent) break; - } while (offset_point.row == 0); - return column; } -TSLength ts_tree_total_size(const TSTree *self) { - return ts_length_add(self->padding, self->size); -} - -TSPoint ts_tree_total_size_point(const TSTree *self) { - return ts_point_add(self->padding_point, self->size_point); +size_t ts_tree_end_column(const TSTree *self) { + size_t result = self->size.columns; + if (self->size.rows == 0) + result += ts_tree_start_column(self); + return result; } bool ts_tree_eq(const TSTree *self, const TSTree *other) { @@ -273,26 +249,26 @@ void ts_tree_edit(TSTree *self, TSInputEdit edit) { size_t start = edit.position; size_t new_end = edit.position + edit.chars_inserted; size_t old_end = edit.position + edit.chars_removed; - assert(old_end <= ts_tree_total_size(self).chars); + assert(old_end <= ts_tree_total_chars(self)); self->options.has_changes = true; if (start < self->padding.chars) { - self->padding.bytes = 0; + ts_length_set_unknown(&self->padding); long remaining_padding = self->padding.chars - old_end; if (remaining_padding >= 0) { self->padding.chars = new_end + remaining_padding; } else { self->padding.chars = new_end; self->size.chars += remaining_padding; - self->size.bytes = 0; + ts_length_set_unknown(&self->size); } } else if (start == self->padding.chars && edit.chars_removed == 0) { - self->padding.bytes = 0; self->padding.chars += edit.chars_inserted; + ts_length_set_unknown(&self->padding); } else { - self->size.bytes = 0; self->size.chars += (edit.chars_inserted - edit.chars_removed); + ts_length_set_unknown(&self->size); } bool found_first_child = false; @@ -300,7 +276,7 @@ void ts_tree_edit(TSTree *self, TSInputEdit edit) { size_t child_left = 0, child_right = 0; for (size_t i = 0; i < self->child_count; i++) { TSTree *child = self->children[i]; - size_t child_size = ts_tree_total_size(child).chars; + size_t child_size = ts_tree_total_chars(child); child_left = child_right; child_right += child_size; diff --git a/src/runtime/tree.h b/src/runtime/tree.h index 28ab3157..cba95741 100644 --- a/src/runtime/tree.h +++ b/src/runtime/tree.h @@ -7,13 +7,13 @@ extern "C" { #include #include "tree_sitter/parser.h" +#include "runtime/length.h" struct TSTree { struct { struct TSTree *parent; size_t index; TSLength offset; - TSPoint offset_point; } context; size_t child_count; size_t visible_child_count; @@ -25,9 +25,6 @@ struct TSTree { TSLength padding; TSLength size; - TSPoint padding_point; - TSPoint size_point; - TSSymbol symbol; struct { @@ -41,12 +38,9 @@ struct TSTree { unsigned short int ref_count; }; -TSTree *ts_tree_make_leaf(TSSymbol, TSLength, TSLength, TSPoint, - TSPoint, TSSymbolMetadata); +TSTree *ts_tree_make_leaf(TSSymbol, TSLength, TSLength, TSSymbolMetadata); TSTree *ts_tree_make_node(TSSymbol, size_t, TSTree **, TSSymbolMetadata); -TSTree *ts_tree_make_error(TSLength size, TSLength padding, - TSPoint padding_point, - TSPoint size_point, char lookahead_char); +TSTree *ts_tree_make_error(TSLength, TSLength, char); void ts_tree_retain(TSTree *tree); void ts_tree_release(TSTree *tree); bool ts_tree_eq(const TSTree *tree1, const TSTree *tree2); @@ -54,13 +48,27 @@ int ts_tree_compare(const TSTree *tree1, const TSTree *tree2); char *ts_tree_string(const TSTree *tree, const char **names, bool include_anonymous); -size_t ts_tree_offset_column(const TSTree *self); -TSLength ts_tree_total_size(const TSTree *tree); -TSPoint ts_tree_total_size_point(const TSTree *self); +size_t ts_tree_start_column(const TSTree *self); +size_t ts_tree_end_column(const TSTree *self); void ts_tree_set_children(TSTree *, size_t, TSTree **); void ts_tree_assign_parents(TSTree *); void ts_tree_edit(TSTree *, TSInputEdit); +static inline size_t ts_tree_total_chars(const TSTree *self) { + return self->padding.chars + self->size.chars; +} + +static inline TSLength ts_tree_total_size(const TSTree *self) { + return ts_length_add(self->padding, self->size); +} + +static inline TSPoint ts_tree_extent(const TSTree *tree) { + TSPoint result; + result.row = tree->size.rows; + result.column = tree->size.columns; + return result; +} + static inline bool ts_tree_is_extra(const TSTree *tree) { return tree->options.extra; }