Rework tree generation mode and API
Store tree nodes in congruent, compact arena array. Define handle types to refer to tree nodes rather than pointers to structure instances. Free tree with context.
This commit is contained in:
1 parent
dddb1b5089
commit
5fc712c6ee
39 files changed
+1349
-811
No files matched your search
@@ -5,24 +5,8 @@
|
||||
|
||||
int main()
|
||||
{
|
||||
/* Grammar (tree generation mode, shared reduce state):
|
||||
* tree;
|
||||
* token a; token b;
|
||||
* start Start;
|
||||
* start R1;
|
||||
* Start -> R1 a;
|
||||
* Start -> R2 b;
|
||||
* R1 -> a b;
|
||||
* R2 -> a b;
|
||||
*
|
||||
* Exercises p_parse_inner_R1() with a non-EOF follow token in tree
|
||||
* generation mode. Verifies:
|
||||
* * The reduced tree for R1 is well-formed after a follow-token
|
||||
* completion.
|
||||
* * The follow token is not consumed and remains available for a
|
||||
* subsequent p_lex() call.
|
||||
* * p_tree_delete_R1() cleans up the returned tree without leaks
|
||||
* (verified in CI via valgrind). */
|
||||
/* See the D variant / grammar comments for details. In tree mode the tree
|
||||
* nodes live in the context arena and are freed with p_context_delete(). */
|
||||
|
||||
/* Baseline: p_parse_R1 works on "ab" and the returned tree is
|
||||
* well-formed. */
|
||||
@@ -30,13 +14,12 @@ int main()
|
||||
char const * input = "ab";
|
||||
p_context_t * context = p_context_new((uint8_t const *)input, strlen(input));
|
||||
assert(p_parse_R1(context) == P_SUCCESS);
|
||||
R1 * tree = p_result_R1(context);
|
||||
assert_not_null(tree);
|
||||
assert_not_null(tree->pToken1);
|
||||
assert_eq((size_t)TOKEN_a, (size_t)tree->pToken1->token);
|
||||
assert_not_null(tree->pToken2);
|
||||
assert_eq((size_t)TOKEN_b, (size_t)tree->pToken2->token);
|
||||
p_tree_delete_R1(tree);
|
||||
R1 tree = p_result_R1(context);
|
||||
assert(p_node_valid(tree));
|
||||
assert(p_node_valid(p_R1_pToken1(tree)));
|
||||
assert_eq((size_t)TOKEN_a, (size_t)p_tree_walk_R1(tree, pToken1, token));
|
||||
assert(p_node_valid(p_R1_pToken2(tree)));
|
||||
assert_eq((size_t)TOKEN_b, (size_t)p_tree_walk_R1(tree, pToken2, token));
|
||||
p_context_delete(context);
|
||||
}
|
||||
|
||||
@@ -50,23 +33,23 @@ int main()
|
||||
assert(p_parse_inner_R1(context, follow_tokens, 1u) == P_SUCCESS);
|
||||
|
||||
/* Tree is well-formed. */
|
||||
R1 * tree = p_result_R1(context);
|
||||
assert_not_null(tree);
|
||||
assert_not_null(tree->pToken1);
|
||||
assert_eq((size_t)TOKEN_a, (size_t)tree->pToken1->token);
|
||||
assert_eq(1u, (size_t)tree->pToken1->position.row);
|
||||
assert_eq(1u, (size_t)tree->pToken1->position.col);
|
||||
assert_not_null(tree->pToken2);
|
||||
assert_eq((size_t)TOKEN_b, (size_t)tree->pToken2->token);
|
||||
assert_eq(1u, (size_t)tree->pToken2->position.row);
|
||||
assert_eq(2u, (size_t)tree->pToken2->position.col);
|
||||
R1 tree = p_result_R1(context);
|
||||
assert(p_node_valid(tree));
|
||||
assert(p_node_valid(p_R1_pToken1(tree)));
|
||||
assert_eq((size_t)TOKEN_a, (size_t)p_tree_walk_R1(tree, pToken1, token));
|
||||
assert_eq(1u, (size_t)p_node_position(p_R1_pToken1(tree)).row);
|
||||
assert_eq(1u, (size_t)p_node_position(p_R1_pToken1(tree)).col);
|
||||
assert(p_node_valid(p_R1_pToken2(tree)));
|
||||
assert_eq((size_t)TOKEN_b, (size_t)p_tree_walk_R1(tree, pToken2, token));
|
||||
assert_eq(1u, (size_t)p_node_position(p_R1_pToken2(tree)).row);
|
||||
assert_eq(2u, (size_t)p_node_position(p_R1_pToken2(tree)).col);
|
||||
|
||||
/* The R1 tree covers positions 1..2 — the third `b` at column 3 is
|
||||
/* The R1 tree covers positions 1..2 - the third `b` at column 3 is
|
||||
* the follow token and is not part of the tree. */
|
||||
assert_eq(1u, (size_t)tree->position.row);
|
||||
assert_eq(1u, (size_t)tree->position.col);
|
||||
assert_eq(1u, (size_t)tree->end_position.row);
|
||||
assert_eq(2u, (size_t)tree->end_position.col);
|
||||
assert_eq(1u, (size_t)p_node_position(tree).row);
|
||||
assert_eq(1u, (size_t)p_node_position(tree).col);
|
||||
assert_eq(1u, (size_t)p_node_end_position(tree).row);
|
||||
assert_eq(2u, (size_t)p_node_end_position(tree).col);
|
||||
|
||||
/* Follow token remains in the input. */
|
||||
p_position_t pos = p_position(context);
|
||||
@@ -78,10 +61,6 @@ int main()
|
||||
assert_eq(1u, (size_t)token_info.position.row);
|
||||
assert_eq(3u, (size_t)token_info.position.col);
|
||||
|
||||
/* p_tree_delete_R1 must free every node reachable from the tree
|
||||
* without leaking anything. valgrind (invoked by the spec runner on
|
||||
* Linux) will detect any missed frees. */
|
||||
p_tree_delete_R1(tree);
|
||||
p_context_delete(context);
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user