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
+43
-12
@@ -751,7 +751,7 @@ EOF
|
||||
|
||||
it "executes user code associated with a parser rule in tree mode" do
|
||||
case language
|
||||
when "c", "cpp"
|
||||
when "c"
|
||||
write_grammar <<EOF
|
||||
tree;
|
||||
context_user_fields <<
|
||||
@@ -769,18 +769,49 @@ ptype int;
|
||||
token a << $$ = 11; >>
|
||||
token b << $$ = 22; >>
|
||||
Start -> A:ay B:bee C <<
|
||||
${context.start_n_fields} = $$->n_fields;
|
||||
${context.start_a_value} = $$->pA->pToken1->pvalue;
|
||||
${context.a_value} = $1->pToken1->pvalue;
|
||||
${context.b_value} = $2->pToken1->pvalue;
|
||||
${context.b_token} = $2->pToken1->token;
|
||||
${context.c_field_is_null} = ($$->pC == NULL) ? 1 : 0;
|
||||
${context.alias_a_value} = ${ay}->pToken1->pvalue;
|
||||
${context.alias_b_value} = ${bee}->pToken1->pvalue;
|
||||
${context.start_n_fields} = p_node_n_fields($$);
|
||||
${context.start_a_value} = p_tree_walk_Start($$, pA, pToken1, pvalue);
|
||||
${context.a_value} = p_tree_walk_A($1, pToken1, pvalue);
|
||||
${context.b_value} = p_tree_walk_B($2, pToken1, pvalue);
|
||||
${context.b_token} = p_tree_walk_B($2, pToken1, token);
|
||||
${context.c_field_is_null} = p_node_valid(p_Start_pC($$)) ? 0 : 1;
|
||||
${context.alias_a_value} = p_tree_walk_A(${ay}, pToken1, pvalue);
|
||||
${context.alias_b_value} = p_tree_walk_B(${bee}, pToken1, pvalue);
|
||||
>>
|
||||
A -> a;
|
||||
B -> b;
|
||||
C -> << ${context.c_is_null} = ($$ == NULL) ? 1 : 0; >>
|
||||
C -> << ${context.c_is_null} = p_node_valid($$) ? 0 : 1; >>
|
||||
EOF
|
||||
when "cpp"
|
||||
write_grammar <<EOF
|
||||
tree;
|
||||
context_user_fields <<
|
||||
int start_n_fields;
|
||||
int start_a_value;
|
||||
int a_value;
|
||||
int b_value;
|
||||
p_token_t b_token;
|
||||
int c_is_null;
|
||||
int c_field_is_null;
|
||||
int alias_a_value;
|
||||
int alias_b_value;
|
||||
>>
|
||||
ptype int;
|
||||
token a << $$ = 11; >>
|
||||
token b << $$ = 22; >>
|
||||
Start -> A:ay B:bee C <<
|
||||
${context.start_n_fields} = $$.n_fields();
|
||||
${context.start_a_value} = $$.pA().pToken1().pvalue();
|
||||
${context.a_value} = $1.pToken1().pvalue();
|
||||
${context.b_value} = $2.pToken1().pvalue();
|
||||
${context.b_token} = $2.pToken1().token();
|
||||
${context.c_field_is_null} = $$.pC().valid() ? 0 : 1;
|
||||
${context.alias_a_value} = ${ay}.pToken1().pvalue();
|
||||
${context.alias_b_value} = ${bee}.pToken1().pvalue();
|
||||
>>
|
||||
A -> a;
|
||||
B -> b;
|
||||
C -> << ${context.c_is_null} = $$.valid() ? 0 : 1; >>
|
||||
EOF
|
||||
when "d"
|
||||
write_grammar <<EOF
|
||||
@@ -805,13 +836,13 @@ Start -> A:ay B:bee C <<
|
||||
${context.a_value} = $1.pToken1.pvalue;
|
||||
${context.b_value} = $2.pToken1.pvalue;
|
||||
${context.b_token} = $2.pToken1.token;
|
||||
${context.c_field_is_null} = ($$.pC is null) ? 1 : 0;
|
||||
${context.c_field_is_null} = ($$.pC.valid) ? 0 : 1;
|
||||
${context.alias_a_value} = ${ay}.pToken1.pvalue;
|
||||
${context.alias_b_value} = ${bee}.pToken1.pvalue;
|
||||
>>
|
||||
A -> a;
|
||||
B -> b;
|
||||
C -> << ${context.c_is_null} = ($$ is null) ? 1 : 0; >>
|
||||
C -> << ${context.c_is_null} = ($$.valid) ? 0 : 1; >>
|
||||
EOF
|
||||
end
|
||||
run_propane(language: language)
|
||||
|
||||
@@ -9,46 +9,42 @@ int main()
|
||||
p_context_t * context;
|
||||
context = p_context_new((uint8_t const *)input, strlen(input));
|
||||
assert(p_parse(context) == P_SUCCESS);
|
||||
Start * start = p_result(context);
|
||||
assert(start->a == NULL);
|
||||
assert(start->pToken2 != NULL);
|
||||
assert_eq(TOKEN_b, start->pToken2->token);
|
||||
assert(start->pR3 == NULL);
|
||||
assert(start->pR == NULL);
|
||||
assert(start->r == NULL);
|
||||
Start start = p_result(context);
|
||||
assert(!p_node_valid(p_Start_a(start)));
|
||||
assert(p_node_valid(p_Start_pToken2(start)));
|
||||
assert_eq(TOKEN_b, p_tree_walk_Start(start, pToken2, token));
|
||||
assert(!p_node_valid(p_Start_pR3(start)));
|
||||
assert(!p_node_valid(p_Start_pR(start)));
|
||||
assert(!p_node_valid(p_Start_r(start)));
|
||||
|
||||
p_tree_delete(start);
|
||||
p_context_delete(context);
|
||||
|
||||
input = "abcd";
|
||||
context = p_context_new((uint8_t const *)input, strlen(input));
|
||||
assert(p_parse(context) == P_SUCCESS);
|
||||
start = p_result(context);
|
||||
assert(start->a != NULL);
|
||||
assert_eq(TOKEN_a, start->pToken1->token);
|
||||
assert(start->pToken2 != NULL);
|
||||
assert(start->pR3 != NULL);
|
||||
assert(start->pR != NULL);
|
||||
assert(start->r != NULL);
|
||||
assert(start->pR == start->pR3);
|
||||
assert(start->pR == start->r);
|
||||
assert_eq(TOKEN_c, start->pR->pToken1->token);
|
||||
assert(p_node_valid(p_Start_a(start)));
|
||||
assert_eq(TOKEN_a, p_tree_walk_Start(start, pToken1, token));
|
||||
assert(p_node_valid(p_Start_pToken2(start)));
|
||||
assert(p_node_valid(p_Start_pR3(start)));
|
||||
assert(p_node_valid(p_Start_pR(start)));
|
||||
assert(p_node_valid(p_Start_r(start)));
|
||||
assert(p_node_id(p_Start_pR(start)) == p_node_id(p_Start_pR3(start)));
|
||||
assert(p_node_id(p_Start_pR(start)) == p_node_id(p_Start_r(start)));
|
||||
assert_eq(TOKEN_c, p_tree_walk_Start(start, pR, pToken1, token));
|
||||
|
||||
p_tree_delete(start);
|
||||
p_context_delete(context);
|
||||
|
||||
input = "bdc";
|
||||
context = p_context_new((uint8_t const *)input, strlen(input));
|
||||
assert(p_parse(context) == P_SUCCESS);
|
||||
start = p_result(context);
|
||||
assert(start->a == NULL);
|
||||
assert(start->pToken2 != NULL);
|
||||
assert(start->r != NULL);
|
||||
assert_eq(TOKEN_d, start->pR->pToken1->token);
|
||||
assert(!p_node_valid(p_Start_a(start)));
|
||||
assert(p_node_valid(p_Start_pToken2(start)));
|
||||
assert(p_node_valid(p_Start_r(start)));
|
||||
assert_eq(TOKEN_d, p_tree_walk_Start(start, pR, pToken1, token));
|
||||
|
||||
p_tree_delete(start);
|
||||
p_context_delete(context);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -12,40 +12,40 @@ unittest
|
||||
string input = "b";
|
||||
p_context_t * context = p_context_new(input);
|
||||
assert(p_parse(context) == P_SUCCESS);
|
||||
Start * start = p_result(context);
|
||||
assert(start.pToken1 is null);
|
||||
assert(start.pToken2 !is null);
|
||||
Start start = p_result(context);
|
||||
assert(!start.pToken1.valid);
|
||||
assert(start.pToken2.valid);
|
||||
assert_eq(TOKEN_b, start.pToken2.token);
|
||||
assert(start.pR3 is null);
|
||||
assert(start.pR is null);
|
||||
assert(start.r is null);
|
||||
assert(!start.pR3.valid);
|
||||
assert(!start.pR.valid);
|
||||
assert(!start.r.valid);
|
||||
|
||||
p_tree_delete(start);
|
||||
p_context_delete(context);
|
||||
|
||||
input = "abcd";
|
||||
context = p_context_new(input);
|
||||
assert(p_parse(context) == P_SUCCESS);
|
||||
start = p_result(context);
|
||||
assert(start.pToken1 != null);
|
||||
assert(start.pToken1.valid);
|
||||
assert_eq(TOKEN_a, start.pToken1.token);
|
||||
assert(start.pToken2 != null);
|
||||
assert(start.pR3 != null);
|
||||
assert(start.pR != null);
|
||||
assert(start.r != null);
|
||||
assert(start.pToken2.valid);
|
||||
assert(start.pR3.valid);
|
||||
assert(start.pR.valid);
|
||||
assert(start.r.valid);
|
||||
assert(start.pR == start.pR3);
|
||||
assert(start.pR == start.r);
|
||||
assert_eq(TOKEN_c, start.pR.pToken1.token);
|
||||
|
||||
p_tree_delete(start);
|
||||
p_context_delete(context);
|
||||
|
||||
input = "bdc";
|
||||
context = p_context_new(input);
|
||||
assert(p_parse(context) == P_SUCCESS);
|
||||
start = p_result(context);
|
||||
assert(start.pToken1 is null);
|
||||
assert(start.pToken2 !is null);
|
||||
assert(start.pR !is null);
|
||||
assert(!start.pToken1.valid);
|
||||
assert(start.pToken2.valid);
|
||||
assert(start.pR.valid);
|
||||
assert_eq(TOKEN_d, start.pR.pToken1.token);
|
||||
|
||||
p_tree_delete(start);
|
||||
p_context_delete(context);
|
||||
}
|
||||
@@ -9,43 +9,39 @@ int main()
|
||||
p_context_t * context;
|
||||
context = p_context_new((uint8_t const *)input, strlen(input));
|
||||
assert(p_parse(context) == P_SUCCESS);
|
||||
Start * start = p_result(context);
|
||||
assert(start->pToken1 == NULL);
|
||||
assert(start->pToken2 != NULL);
|
||||
assert_eq(TOKEN_b, start->pToken2->token);
|
||||
assert(start->pR3 == NULL);
|
||||
assert(start->pR == NULL);
|
||||
Start start = p_result(context);
|
||||
assert(!p_node_valid(p_Start_pToken1(start)));
|
||||
assert(p_node_valid(p_Start_pToken2(start)));
|
||||
assert_eq(TOKEN_b, p_tree_walk_Start(start, pToken2, token));
|
||||
assert(!p_node_valid(p_Start_pR3(start)));
|
||||
assert(!p_node_valid(p_Start_pR(start)));
|
||||
|
||||
p_tree_delete(start);
|
||||
p_context_delete(context);
|
||||
|
||||
input = "abcd";
|
||||
context = p_context_new((uint8_t const *)input, strlen(input));
|
||||
assert(p_parse(context) == P_SUCCESS);
|
||||
start = p_result(context);
|
||||
assert(start->pToken1 != NULL);
|
||||
assert_eq(TOKEN_a, start->pToken1->token);
|
||||
assert(start->pToken2 != NULL);
|
||||
assert(start->pR3 != NULL);
|
||||
assert(start->pR != NULL);
|
||||
assert(start->pR == start->pR3);
|
||||
assert_eq(TOKEN_c, start->pR->pToken1->token);
|
||||
assert(p_node_valid(p_Start_pToken1(start)));
|
||||
assert_eq(TOKEN_a, p_tree_walk_Start(start, pToken1, token));
|
||||
assert(p_node_valid(p_Start_pToken2(start)));
|
||||
assert(p_node_valid(p_Start_pR3(start)));
|
||||
assert(p_node_valid(p_Start_pR(start)));
|
||||
assert(p_node_id(p_Start_pR(start)) == p_node_id(p_Start_pR3(start)));
|
||||
assert_eq(TOKEN_c, p_tree_walk_Start(start, pR, pToken1, token));
|
||||
|
||||
p_tree_delete(start);
|
||||
p_context_delete(context);
|
||||
|
||||
input = "bdc";
|
||||
context = p_context_new((uint8_t const *)input, strlen(input));
|
||||
assert(p_parse(context) == P_SUCCESS);
|
||||
start = p_result(context);
|
||||
assert(start->pToken1 == NULL);
|
||||
assert(start->pToken2 != NULL);
|
||||
assert(start->pR != NULL);
|
||||
assert_eq(TOKEN_d, start->pR->pToken1->token);
|
||||
assert(!p_node_valid(p_Start_pToken1(start)));
|
||||
assert(p_node_valid(p_Start_pToken2(start)));
|
||||
assert(p_node_valid(p_Start_pR(start)));
|
||||
assert_eq(TOKEN_d, p_tree_walk_Start(start, pR, pToken1, token));
|
||||
|
||||
p_tree_delete(start);
|
||||
p_context_delete(context);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -12,37 +12,37 @@ unittest
|
||||
string input = "b";
|
||||
p_context_t * context = p_context_new(input);
|
||||
assert(p_parse(context) == P_SUCCESS);
|
||||
Start * start = p_result(context);
|
||||
assert(start.pToken1 is null);
|
||||
assert(start.pToken2 !is null);
|
||||
Start start = p_result(context);
|
||||
assert(!start.pToken1.valid);
|
||||
assert(start.pToken2.valid);
|
||||
assert_eq(TOKEN_b, start.pToken2.token);
|
||||
assert(start.pR3 is null);
|
||||
assert(start.pR is null);
|
||||
assert(!start.pR3.valid);
|
||||
assert(!start.pR.valid);
|
||||
|
||||
p_tree_delete(start);
|
||||
p_context_delete(context);
|
||||
|
||||
input = "abcd";
|
||||
context = p_context_new(input);
|
||||
assert(p_parse(context) == P_SUCCESS);
|
||||
start = p_result(context);
|
||||
assert(start.pToken1 != null);
|
||||
assert(start.pToken1.valid);
|
||||
assert_eq(TOKEN_a, start.pToken1.token);
|
||||
assert(start.pToken2 != null);
|
||||
assert(start.pR3 != null);
|
||||
assert(start.pR != null);
|
||||
assert(start.pToken2.valid);
|
||||
assert(start.pR3.valid);
|
||||
assert(start.pR.valid);
|
||||
assert(start.pR == start.pR3);
|
||||
assert_eq(TOKEN_c, start.pR.pToken1.token);
|
||||
|
||||
p_tree_delete(start);
|
||||
p_context_delete(context);
|
||||
|
||||
input = "bdc";
|
||||
context = p_context_new(input);
|
||||
assert(p_parse(context) == P_SUCCESS);
|
||||
start = p_result(context);
|
||||
assert(start.pToken1 is null);
|
||||
assert(start.pToken2 !is null);
|
||||
assert(start.pR !is null);
|
||||
assert(!start.pToken1.valid);
|
||||
assert(start.pToken2.valid);
|
||||
assert(start.pR.valid);
|
||||
assert_eq(TOKEN_d, start.pR.pToken1.token);
|
||||
|
||||
p_tree_delete(start);
|
||||
p_context_delete(context);
|
||||
}
|
||||
@@ -3,21 +3,8 @@
|
||||
#include <string.h>
|
||||
#include "testutils.h"
|
||||
|
||||
/* Grammar (tree generation mode; parentheses handled by the lex function):
|
||||
* tree;
|
||||
* lex_fn mylexfn;
|
||||
* token lparen /\(/; token rparen /\)/; token plus /\+/; token num /\d+/;
|
||||
* Start -> Expr;
|
||||
* Expr -> num;
|
||||
* Expr -> Expr plus num;
|
||||
*
|
||||
* The same lexer-driven nested parse as test_parse_inner_nested, but in tree
|
||||
* generation mode. Each "( ... )" group is parsed by a reentrant
|
||||
* p_parse_inner_Start() call from the lex function; the resulting subtree is
|
||||
* discarded and a single synthesized num token is handed to the outer parse.
|
||||
* The synthesized token's position is set to span the whole group ('(' start
|
||||
* through ')' end), so this verifies that positions survive the nested-parse
|
||||
* boundary and land correctly in the outer tree. */
|
||||
/* Grammar: see the D variant / spec. Tree generation mode; parentheses handled
|
||||
* by the lex function. Tree nodes live in the context arena. */
|
||||
|
||||
size_t mylexfn(p_context_t * context, p_token_info_t * out_token_info)
|
||||
{
|
||||
@@ -36,8 +23,8 @@ size_t mylexfn(p_context_t * context, p_token_info_t * out_token_info)
|
||||
{
|
||||
return inner_result;
|
||||
}
|
||||
Start * inner = p_result_Start(context);
|
||||
assert_not_null(inner);
|
||||
Start inner = p_result_Start(context);
|
||||
assert(p_node_valid(inner));
|
||||
/* p_parse_inner rewound the input so that ')' was not consumed; consume
|
||||
* it now. */
|
||||
p_token_info_t rparen_info;
|
||||
@@ -45,10 +32,11 @@ size_t mylexfn(p_context_t * context, p_token_info_t * out_token_info)
|
||||
assert(rparen_result == P_SUCCESS);
|
||||
assert(rparen_info.token == TOKEN_rparen);
|
||||
/* The subtree covers the region strictly between the parentheses. */
|
||||
assert_eq((size_t)(start_position.col + 1u), (size_t)inner->position.col);
|
||||
assert_eq((size_t)(rparen_info.position.col - 1u), (size_t)inner->end_position.col);
|
||||
p_tree_delete_Start(inner);
|
||||
/* Synthesize a num token spanning the entire "( ... )" group. */
|
||||
assert_eq((size_t)(start_position.col + 1u), (size_t)p_node_position(inner).col);
|
||||
assert_eq((size_t)(rparen_info.position.col - 1u), (size_t)p_node_end_position(inner).col);
|
||||
/* The inner subtree is discarded (the lexer synthesizes a num token in
|
||||
* its place), but its nodes remain in the shared context arena and are
|
||||
* freed with the context. */
|
||||
out_token_info->token = TOKEN_num;
|
||||
out_token_info->position = start_position;
|
||||
out_token_info->end_position = rparen_info.end_position;
|
||||
@@ -64,40 +52,39 @@ int main()
|
||||
p_context_t * context = p_context_new((uint8_t const *)input, strlen(input));
|
||||
assert(p_parse(context) == P_SUCCESS);
|
||||
|
||||
Start * tree = p_result(context);
|
||||
assert_not_null(tree);
|
||||
Start tree = p_result(context);
|
||||
assert(p_node_valid(tree));
|
||||
|
||||
/* Start -> Expr, where the top Expr is "Expr plus num". */
|
||||
Expr * top = tree->pExpr;
|
||||
assert_not_null(top);
|
||||
assert_not_null(top->pExpr);
|
||||
assert_not_null(top->pToken2);
|
||||
assert_not_null(top->pToken3);
|
||||
Expr top = p_Start_pExpr(tree);
|
||||
assert(p_node_valid(top));
|
||||
assert(p_node_valid(p_Expr_pExpr(top)));
|
||||
assert(p_node_valid(p_Expr_pToken2(top)));
|
||||
assert(p_node_valid(p_Expr_pToken3(top)));
|
||||
|
||||
/* The '+' joining the two groups is at column 9. */
|
||||
assert_eq(1u, (size_t)top->pToken2->position.row);
|
||||
assert_eq(9u, (size_t)top->pToken2->position.col);
|
||||
assert_eq(1u, (size_t)p_node_position(p_Expr_pToken2(top)).row);
|
||||
assert_eq(9u, (size_t)p_node_position(p_Expr_pToken2(top)).col);
|
||||
|
||||
/* Right operand: synthesized num for "(5 + 6)", spanning columns 11..17. */
|
||||
assert_eq(1u, (size_t)top->pToken3->position.row);
|
||||
assert_eq(11u, (size_t)top->pToken3->position.col);
|
||||
assert_eq(1u, (size_t)top->pToken3->end_position.row);
|
||||
assert_eq(17u, (size_t)top->pToken3->end_position.col);
|
||||
assert_eq(1u, (size_t)p_node_position(p_Expr_pToken3(top)).row);
|
||||
assert_eq(11u, (size_t)p_node_position(p_Expr_pToken3(top)).col);
|
||||
assert_eq(1u, (size_t)p_node_end_position(p_Expr_pToken3(top)).row);
|
||||
assert_eq(17u, (size_t)p_node_end_position(p_Expr_pToken3(top)).col);
|
||||
|
||||
/* Left operand: Expr -> num, the synthesized num for "(3 + 4)", spanning
|
||||
* columns 1..7. */
|
||||
Expr * left = top->pExpr;
|
||||
assert_not_null(left->pToken1);
|
||||
assert_eq(1u, (size_t)left->pToken1->position.row);
|
||||
assert_eq(1u, (size_t)left->pToken1->position.col);
|
||||
assert_eq(1u, (size_t)left->pToken1->end_position.row);
|
||||
assert_eq(7u, (size_t)left->pToken1->end_position.col);
|
||||
Expr left = p_Expr_pExpr(top);
|
||||
assert(p_node_valid(p_Expr_pToken1(left)));
|
||||
assert_eq(1u, (size_t)p_node_position(p_Expr_pToken1(left)).row);
|
||||
assert_eq(1u, (size_t)p_node_position(p_Expr_pToken1(left)).col);
|
||||
assert_eq(1u, (size_t)p_node_end_position(p_Expr_pToken1(left)).row);
|
||||
assert_eq(7u, (size_t)p_node_end_position(p_Expr_pToken1(left)).col);
|
||||
|
||||
/* The whole tree spans columns 1..17. */
|
||||
assert_eq(1u, (size_t)tree->position.col);
|
||||
assert_eq(17u, (size_t)tree->end_position.col);
|
||||
assert_eq(1u, (size_t)p_node_position(tree).col);
|
||||
assert_eq(17u, (size_t)p_node_end_position(tree).col);
|
||||
|
||||
p_tree_delete(tree);
|
||||
p_context_delete(context);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -20,8 +20,8 @@ size_t mylexfn(p_context_t * context, p_token_info_t * out_token_info)
|
||||
{
|
||||
return inner_result;
|
||||
}
|
||||
Start * inner = p_result_Start(context);
|
||||
assert(inner !is null);
|
||||
Start inner = p_result_Start(context);
|
||||
assert(inner.valid);
|
||||
/* p_parse_inner rewound the input so that ')' was not consumed; consume
|
||||
* it now. */
|
||||
p_token_info_t rparen_info;
|
||||
@@ -31,7 +31,9 @@ size_t mylexfn(p_context_t * context, p_token_info_t * out_token_info)
|
||||
/* The subtree covers the region strictly between the parentheses. */
|
||||
assert_eq(start_position.col + 1u, inner.position.col);
|
||||
assert_eq(rparen_info.position.col - 1u, inner.end_position.col);
|
||||
p_tree_delete_Start(inner);
|
||||
/* The inner subtree is discarded (the lexer synthesizes a num token in
|
||||
* its place), but its nodes remain in the shared context arena and are
|
||||
* freed with the context. */
|
||||
/* Synthesize a num token spanning the entire "( ... )" group. */
|
||||
out_token_info.token = TOKEN_num;
|
||||
out_token_info.position = start_position;
|
||||
@@ -53,15 +55,15 @@ unittest
|
||||
p_context_t * context = p_context_new(input);
|
||||
assert(p_parse(context) == P_SUCCESS);
|
||||
|
||||
Start * tree = p_result(context);
|
||||
assert(tree !is null);
|
||||
Start tree = p_result(context);
|
||||
assert(tree.valid);
|
||||
|
||||
/* Start -> Expr, where the top Expr is "Expr plus num". */
|
||||
Expr * top = tree.pExpr;
|
||||
assert(top !is null);
|
||||
assert(top.pExpr !is null);
|
||||
assert(top.pToken2 !is null);
|
||||
assert(top.pToken3 !is null);
|
||||
Expr top = tree.pExpr;
|
||||
assert(top.valid);
|
||||
assert(top.pExpr.valid);
|
||||
assert(top.pToken2.valid);
|
||||
assert(top.pToken3.valid);
|
||||
|
||||
/* The '+' joining the two groups is at column 9. */
|
||||
assert_eq(1u, top.pToken2.position.row);
|
||||
@@ -75,8 +77,8 @@ unittest
|
||||
|
||||
/* Left operand: Expr -> num, the synthesized num for "(3 + 4)", spanning
|
||||
* columns 1..7. */
|
||||
Expr * left = top.pExpr;
|
||||
assert(left.pToken1 !is null);
|
||||
Expr left = top.pExpr;
|
||||
assert(left.pToken1.valid);
|
||||
assert_eq(1u, left.pToken1.position.row);
|
||||
assert_eq(1u, left.pToken1.position.col);
|
||||
assert_eq(1u, left.pToken1.end_position.row);
|
||||
@@ -86,6 +88,5 @@ unittest
|
||||
assert_eq(1u, tree.position.col);
|
||||
assert_eq(17u, tree.end_position.col);
|
||||
|
||||
p_tree_delete(tree);
|
||||
p_context_delete(context);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,13 +16,13 @@ unittest
|
||||
string input = "ab";
|
||||
p_context_t * context = p_context_new(input);
|
||||
assert(p_parse_R1(context) == P_SUCCESS);
|
||||
R1 * tree = p_result_R1(context);
|
||||
assert(tree !is null);
|
||||
assert(tree.pToken1 !is null);
|
||||
R1 tree = p_result_R1(context);
|
||||
assert(tree.valid);
|
||||
assert(tree.pToken1.valid);
|
||||
assert(tree.pToken1.token == TOKEN_a);
|
||||
assert(tree.pToken2 !is null);
|
||||
assert(tree.pToken2.valid);
|
||||
assert(tree.pToken2.token == TOKEN_b);
|
||||
p_tree_delete_R1(tree);
|
||||
p_context_delete(context);
|
||||
}
|
||||
|
||||
/* Primary case: p_parse_inner_R1 with a non-EOF follow token completes
|
||||
@@ -35,13 +35,13 @@ unittest
|
||||
assert(p_parse_inner_R1(context, follow_tokens) == P_SUCCESS);
|
||||
|
||||
/* Tree is well-formed. */
|
||||
R1 * tree = p_result_R1(context);
|
||||
assert(tree !is null);
|
||||
assert(tree.pToken1 !is null);
|
||||
R1 tree = p_result_R1(context);
|
||||
assert(tree.valid);
|
||||
assert(tree.pToken1.valid);
|
||||
assert(tree.pToken1.token == TOKEN_a);
|
||||
assert(tree.pToken1.position.row == 1);
|
||||
assert(tree.pToken1.position.col == 1);
|
||||
assert(tree.pToken2 !is null);
|
||||
assert(tree.pToken2.valid);
|
||||
assert(tree.pToken2.token == TOKEN_b);
|
||||
assert(tree.pToken2.position.row == 1);
|
||||
assert(tree.pToken2.position.col == 2);
|
||||
@@ -63,6 +63,6 @@ unittest
|
||||
assert(token_info.position.row == 1);
|
||||
assert(token_info.position.col == 3);
|
||||
|
||||
p_tree_delete_R1(tree);
|
||||
p_context_delete(context);
|
||||
}
|
||||
}
|
||||
@@ -28,11 +28,10 @@ int main()
|
||||
assert_eq(11, context->alias_a_value);
|
||||
assert_eq(22, context->alias_b_value);
|
||||
|
||||
Start * start = p_result(context);
|
||||
assert(start->pA != NULL);
|
||||
assert(start->pB != NULL);
|
||||
assert(start->pC == NULL);
|
||||
p_tree_delete(start);
|
||||
Start start = p_result(context);
|
||||
assert(p_node_valid(p_Start_pA(start)));
|
||||
assert(p_node_valid(p_Start_pB(start)));
|
||||
assert(!p_node_valid(p_Start_pC(start)));
|
||||
p_context_delete(context);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -31,9 +31,9 @@ unittest
|
||||
assert_eq(11, context.alias_a_value);
|
||||
assert_eq(22, context.alias_b_value);
|
||||
|
||||
Start * start = p_result(context);
|
||||
assert(start.pA !is null);
|
||||
assert(start.pB !is null);
|
||||
assert(start.pC is null);
|
||||
p_tree_delete(start);
|
||||
Start start = p_result(context);
|
||||
assert(start.pA.valid);
|
||||
assert(start.pB.valid);
|
||||
assert(!start.pC.valid);
|
||||
p_context_delete(context);
|
||||
}
|
||||
@@ -9,11 +9,10 @@ int main()
|
||||
p_context_t * context;
|
||||
context = p_context_new((uint8_t const *)input, strlen(input));
|
||||
assert_eq(P_SUCCESS, p_parse(context));
|
||||
Top * top = p_result(context);
|
||||
assert(top->pToken != NULL);
|
||||
assert_eq(TOKEN_hi, top->pToken->token);
|
||||
Top top = p_result(context);
|
||||
assert(p_node_valid(p_Top_pToken(top)));
|
||||
assert_eq(TOKEN_hi, p_tree_walk_Top(top, pToken, token));
|
||||
|
||||
p_tree_delete(top);
|
||||
p_context_delete(context);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -13,7 +13,7 @@ unittest
|
||||
p_context_t * context;
|
||||
context = p_context_new(input);
|
||||
assert_eq(P_SUCCESS, p_parse(context));
|
||||
Top * top = p_result(context);
|
||||
assert(top.pToken !is null);
|
||||
Top top = p_result(context);
|
||||
assert(top.pToken.valid);
|
||||
assert_eq(TOKEN_hi, top.pToken.token);
|
||||
}
|
||||
@@ -9,31 +9,28 @@ int main()
|
||||
p_context_t * context;
|
||||
context = p_context_new((uint8_t const *)input, strlen(input));
|
||||
assert(p_parse(context) == P_SUCCESS);
|
||||
Start * start = p_result(context);
|
||||
assert_not_null(start->bs);
|
||||
assert_not_null(start->bs->b);
|
||||
assert_not_null(start->bs->bs->b);
|
||||
assert_not_null(start->bs->bs->bs->b);
|
||||
assert_not_null(start->bs->bs->bs->bs->b);
|
||||
p_tree_delete(start);
|
||||
Start start = p_result(context);
|
||||
assert(p_node_valid(p_Start_bs(start)));
|
||||
assert(p_node_valid(p_tree_walk_Start(start, bs, b)));
|
||||
assert(p_node_valid(p_tree_walk_Start(start, bs, bs, b)));
|
||||
assert(p_node_valid(p_tree_walk_Start(start, bs, bs, bs, b)));
|
||||
assert(p_node_valid(p_tree_walk_Start(start, bs, bs, bs, bs, b)));
|
||||
p_context_delete(context);
|
||||
|
||||
context = p_context_new((uint8_t const *)input, strlen(input));
|
||||
assert(p_parse_Bs(context) == P_SUCCESS);
|
||||
Bs * bs = p_result_Bs(context);
|
||||
assert_not_null(bs->b);
|
||||
assert_not_null(bs->bs->b);
|
||||
assert_not_null(bs->bs->bs->b);
|
||||
assert_not_null(bs->bs->bs->bs->b);
|
||||
p_tree_delete_Bs(bs);
|
||||
Bs bs = p_result_Bs(context);
|
||||
assert(p_node_valid(p_Bs_b(bs)));
|
||||
assert(p_node_valid(p_tree_walk_Bs(bs, bs, b)));
|
||||
assert(p_node_valid(p_tree_walk_Bs(bs, bs, bs, b)));
|
||||
assert(p_node_valid(p_tree_walk_Bs(bs, bs, bs, bs, b)));
|
||||
p_context_delete(context);
|
||||
|
||||
input = "c";
|
||||
context = p_context_new((uint8_t const *)input, strlen(input));
|
||||
assert(p_parse_R(context) == P_SUCCESS);
|
||||
R * r = p_result_R(context);
|
||||
assert_not_null(r->c);
|
||||
p_tree_delete_R(r);
|
||||
R r = p_result_R(context);
|
||||
assert(p_node_valid(p_R_c(r)));
|
||||
p_context_delete(context);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -12,30 +12,30 @@ unittest
|
||||
string input = "bbbb";
|
||||
p_context_t * context = p_context_new(input);
|
||||
assert(p_parse(context) == P_SUCCESS);
|
||||
Start * start = p_result(context);
|
||||
assert(start.bs);
|
||||
assert(start.bs.b);
|
||||
assert(start.bs.bs.b);
|
||||
assert(start.bs.bs.bs.b);
|
||||
assert(start.bs.bs.bs.bs.b);
|
||||
Start start = p_result(context);
|
||||
assert(start.bs.valid);
|
||||
assert(start.bs.b.valid);
|
||||
assert(start.bs.bs.b.valid);
|
||||
assert(start.bs.bs.bs.b.valid);
|
||||
assert(start.bs.bs.bs.bs.b.valid);
|
||||
|
||||
p_tree_delete(start);
|
||||
p_context_delete(context);
|
||||
|
||||
context = p_context_new(input);
|
||||
assert(p_parse_Bs(context) == P_SUCCESS);
|
||||
Bs * bs = p_result_Bs(context);
|
||||
assert(bs.b);
|
||||
assert(bs.bs.b);
|
||||
assert(bs.bs.bs.b);
|
||||
assert(bs.bs.bs.bs.b);
|
||||
Bs bs = p_result_Bs(context);
|
||||
assert(bs.b.valid);
|
||||
assert(bs.bs.b.valid);
|
||||
assert(bs.bs.bs.b.valid);
|
||||
assert(bs.bs.bs.bs.b.valid);
|
||||
|
||||
p_tree_delete_Bs(bs);
|
||||
p_context_delete(context);
|
||||
|
||||
input = "c";
|
||||
context = p_context_new(input);
|
||||
assert(p_parse_R(context) == P_SUCCESS);
|
||||
R * r = p_result_R(context);
|
||||
assert(r.c);
|
||||
R r = p_result_R(context);
|
||||
assert(r.c.valid);
|
||||
|
||||
p_tree_delete_R(r);
|
||||
p_context_delete(context);
|
||||
}
|
||||
@@ -18,29 +18,22 @@ int main()
|
||||
p_context_t * context;
|
||||
context = p_context_new((uint8_t const *)input, strlen(input));
|
||||
assert(p_parse(context) == P_SUCCESS);
|
||||
Start * start = p_result(context);
|
||||
assert(start->pIDs);
|
||||
assert(start->pIDs->id);
|
||||
#ifdef __cplusplus
|
||||
assert(start->pIDs->id->comments == "# c1\n# c2\n");
|
||||
#else
|
||||
assert(start->pIDs->id->comments);
|
||||
assert(strcmp(start->pIDs->id->comments, "# c1\n# c2\n") == 0);
|
||||
#endif
|
||||
assert(start->pIDs->pIDs);
|
||||
assert(start->pIDs->pIDs->id);
|
||||
#ifdef __cplusplus
|
||||
assert(start->pIDs->pIDs->id->comments == "# s1\n# s2\n");
|
||||
#else
|
||||
assert(start->pIDs->pIDs->id->comments);
|
||||
assert(strcmp(start->pIDs->pIDs->id->comments, "# s1\n# s2\n") == 0);
|
||||
#endif
|
||||
Start start = p_result(context);
|
||||
IDs ids = p_Start_pIDs(start);
|
||||
assert(p_node_valid(ids));
|
||||
Token id0 = p_IDs_id(ids);
|
||||
assert(p_node_valid(id0));
|
||||
assert(p_node_data(id0)->comments);
|
||||
assert(strcmp(p_node_data(id0)->comments, "# c1\n# c2\n") == 0);
|
||||
IDs ids2 = p_IDs_pIDs(ids);
|
||||
assert(p_node_valid(ids2));
|
||||
Token id1 = p_IDs_id(ids2);
|
||||
assert(p_node_valid(id1));
|
||||
assert(p_node_data(id1)->comments);
|
||||
assert(strcmp(p_node_data(id1)->comments, "# s1\n# s2\n") == 0);
|
||||
|
||||
#ifndef __cplusplus
|
||||
free(context->comments);
|
||||
#endif
|
||||
p_context_delete(context);
|
||||
p_tree_delete(start);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#include "testparser.h"
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
int main()
|
||||
{
|
||||
char const * input =
|
||||
"# c1\n"
|
||||
"# c2\n"
|
||||
"\n"
|
||||
"first\n"
|
||||
"\n \n \n"
|
||||
" # s1\n"
|
||||
" # s2\n"
|
||||
"second\n";
|
||||
p_context_t * context;
|
||||
context = p_context_new((uint8_t const *)input, strlen(input));
|
||||
assert(p_parse(context) == P_SUCCESS);
|
||||
Start start = p_result(context);
|
||||
assert(start.pIDs().valid());
|
||||
assert(start.pIDs().id().valid());
|
||||
assert(start.pIDs().id().data()->comments == "# c1\n# c2\n");
|
||||
assert(start.pIDs().pIDs().valid());
|
||||
assert(start.pIDs().pIDs().id().valid());
|
||||
assert(start.pIDs().pIDs().id().data()->comments == "# s1\n# s2\n");
|
||||
|
||||
p_context_delete(context);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -19,13 +19,13 @@ unittest
|
||||
"second\n";
|
||||
p_context_t * context = p_context_new(input);
|
||||
assert(p_parse(context) == P_SUCCESS);
|
||||
Start * start = p_result(context);
|
||||
assert(start.pIDs);
|
||||
assert(start.pIDs.id);
|
||||
Start start = p_result(context);
|
||||
assert(start.pIDs.valid);
|
||||
assert(start.pIDs.id.valid);
|
||||
assert(start.pIDs.id.comments == "# c1\n# c2\n");
|
||||
assert(start.pIDs.pIDs);
|
||||
assert(start.pIDs.pIDs.id);
|
||||
assert(start.pIDs.pIDs.valid);
|
||||
assert(start.pIDs.pIDs.id.valid);
|
||||
assert(start.pIDs.pIDs.id.comments == "# s1\n# s2\n");
|
||||
|
||||
p_tree_delete(start);
|
||||
p_context_delete(context);
|
||||
}
|
||||
+31
-34
@@ -9,55 +9,52 @@ int main()
|
||||
p_context_t * context;
|
||||
context = p_context_new((uint8_t const *)input, strlen(input));
|
||||
assert_eq(P_SUCCESS, p_parse(context));
|
||||
Start * start = p_result(context);
|
||||
assert(start->pItems1 != NULL);
|
||||
assert(start->pItems != NULL);
|
||||
Items * items = start->pItems;
|
||||
assert(items->pItem != NULL);
|
||||
assert(items->pItem->pToken1 != NULL);
|
||||
assert_eq(TOKEN_a, items->pItem->pToken1->token);
|
||||
assert_eq(11, items->pItem->pToken1->pvalue);
|
||||
assert(items->pItemsMore != NULL);
|
||||
ItemsMore * itemsmore = items->pItemsMore;
|
||||
assert(itemsmore->pItem != NULL);
|
||||
assert(itemsmore->pItem->pItem != NULL);
|
||||
assert(itemsmore->pItem->pItem->pItem != NULL);
|
||||
assert(itemsmore->pItem->pItem->pItem->pToken1 != NULL);
|
||||
assert_eq(TOKEN_b, itemsmore->pItem->pItem->pItem->pToken1->token);
|
||||
assert_eq(22, itemsmore->pItem->pItem->pItem->pToken1->pvalue);
|
||||
assert(itemsmore->pItemsMore != NULL);
|
||||
itemsmore = itemsmore->pItemsMore;
|
||||
assert(itemsmore->pItem != NULL);
|
||||
assert(itemsmore->pItem->pToken1 != NULL);
|
||||
assert_eq(TOKEN_b, itemsmore->pItem->pToken1->token);
|
||||
assert_eq(22, itemsmore->pItem->pToken1->pvalue);
|
||||
assert(itemsmore->pItemsMore == NULL);
|
||||
Start start = p_result(context);
|
||||
assert(p_node_valid(p_Start_pItems1(start)));
|
||||
assert(p_node_valid(p_Start_pItems(start)));
|
||||
Items items = p_Start_pItems(start);
|
||||
assert(p_node_valid(p_Items_pItem(items)));
|
||||
assert(p_node_valid(p_tree_walk_Items(items, pItem, pToken1)));
|
||||
assert_eq(TOKEN_a, p_tree_walk_Items(items, pItem, pToken1, token));
|
||||
assert_eq(11, p_tree_walk_Items(items, pItem, pToken1, pvalue));
|
||||
assert(p_node_valid(p_Items_pItemsMore(items)));
|
||||
ItemsMore itemsmore = p_Items_pItemsMore(items);
|
||||
assert(p_node_valid(p_ItemsMore_pItem(itemsmore)));
|
||||
assert(p_node_valid(p_tree_walk_ItemsMore(itemsmore, pItem, pItem)));
|
||||
assert(p_node_valid(p_tree_walk_ItemsMore(itemsmore, pItem, pItem, pItem)));
|
||||
assert(p_node_valid(p_tree_walk_ItemsMore(itemsmore, pItem, pItem, pItem, pToken1)));
|
||||
assert_eq(TOKEN_b, p_tree_walk_ItemsMore(itemsmore, pItem, pItem, pItem, pToken1, token));
|
||||
assert_eq(22, p_tree_walk_ItemsMore(itemsmore, pItem, pItem, pItem, pToken1, pvalue));
|
||||
assert(p_node_valid(p_ItemsMore_pItemsMore(itemsmore)));
|
||||
itemsmore = p_ItemsMore_pItemsMore(itemsmore);
|
||||
assert(p_node_valid(p_ItemsMore_pItem(itemsmore)));
|
||||
assert(p_node_valid(p_tree_walk_ItemsMore(itemsmore, pItem, pToken1)));
|
||||
assert_eq(TOKEN_b, p_tree_walk_ItemsMore(itemsmore, pItem, pToken1, token));
|
||||
assert_eq(22, p_tree_walk_ItemsMore(itemsmore, pItem, pToken1, pvalue));
|
||||
assert(!p_node_valid(p_ItemsMore_pItemsMore(itemsmore)));
|
||||
|
||||
p_tree_delete(start);
|
||||
p_context_delete(context);
|
||||
|
||||
input = "";
|
||||
context = p_context_new((uint8_t const *)input, strlen(input));
|
||||
assert_eq(P_SUCCESS, p_parse(context));
|
||||
start = p_result(context);
|
||||
assert(start->pItems == NULL);
|
||||
assert(!p_node_valid(p_Start_pItems(start)));
|
||||
|
||||
p_tree_delete(start);
|
||||
p_context_delete(context);
|
||||
|
||||
input = "2 1";
|
||||
context = p_context_new((uint8_t const *)input, strlen(input));
|
||||
assert_eq(P_SUCCESS, p_parse(context));
|
||||
start = p_result(context);
|
||||
assert(start->pItems != NULL);
|
||||
assert(start->pItems->pItem != NULL);
|
||||
assert(start->pItems->pItem->pDual != NULL);
|
||||
assert(start->pItems->pItem->pDual->pTwo1 != NULL);
|
||||
assert(start->pItems->pItem->pDual->pOne2 != NULL);
|
||||
assert(start->pItems->pItem->pDual->pTwo2 == NULL);
|
||||
assert(start->pItems->pItem->pDual->pOne1 == NULL);
|
||||
assert(p_node_valid(p_Start_pItems(start)));
|
||||
assert(p_node_valid(p_tree_walk_Start(start, pItems, pItem)));
|
||||
assert(p_node_valid(p_tree_walk_Start(start, pItems, pItem, pDual)));
|
||||
assert(p_node_valid(p_tree_walk_Start(start, pItems, pItem, pDual, pTwo1)));
|
||||
assert(p_node_valid(p_tree_walk_Start(start, pItems, pItem, pDual, pOne2)));
|
||||
assert(!p_node_valid(p_tree_walk_Start(start, pItems, pItem, pDual, pTwo2)));
|
||||
assert(!p_node_valid(p_tree_walk_Start(start, pItems, pItem, pDual, pOne1)));
|
||||
|
||||
p_tree_delete(start);
|
||||
p_context_delete(context);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
#include "testparser.h"
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include "testutils.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
char const * input = "a, ((b)), b";
|
||||
p_context_t * context;
|
||||
context = p_context_new((uint8_t const *)input, strlen(input));
|
||||
assert_eq(P_SUCCESS, p_parse(context));
|
||||
Start start = p_result(context);
|
||||
assert(start.pItems1().valid());
|
||||
assert(start.pItems().valid());
|
||||
Items items = start.pItems();
|
||||
assert(items.pItem().valid());
|
||||
assert(items.pItem().pToken1().valid());
|
||||
assert_eq(TOKEN_a, items.pItem().pToken1().token());
|
||||
assert_eq(11, items.pItem().pToken1().pvalue());
|
||||
assert(items.pItemsMore().valid());
|
||||
ItemsMore itemsmore = items.pItemsMore();
|
||||
assert(itemsmore.pItem().valid());
|
||||
assert(itemsmore.pItem().pItem().valid());
|
||||
assert(itemsmore.pItem().pItem().pItem().valid());
|
||||
assert(itemsmore.pItem().pItem().pItem().pToken1().valid());
|
||||
assert_eq(TOKEN_b, itemsmore.pItem().pItem().pItem().pToken1().token());
|
||||
assert_eq(22, itemsmore.pItem().pItem().pItem().pToken1().pvalue());
|
||||
assert(itemsmore.pItemsMore().valid());
|
||||
itemsmore = itemsmore.pItemsMore();
|
||||
assert(itemsmore.pItem().valid());
|
||||
assert(itemsmore.pItem().pToken1().valid());
|
||||
assert_eq(TOKEN_b, itemsmore.pItem().pToken1().token());
|
||||
assert_eq(22, itemsmore.pItem().pToken1().pvalue());
|
||||
assert(!itemsmore.pItemsMore().valid());
|
||||
|
||||
p_context_delete(context);
|
||||
|
||||
input = "";
|
||||
context = p_context_new((uint8_t const *)input, strlen(input));
|
||||
assert_eq(P_SUCCESS, p_parse(context));
|
||||
start = p_result(context);
|
||||
assert(!start.pItems().valid());
|
||||
|
||||
p_context_delete(context);
|
||||
|
||||
input = "2 1";
|
||||
context = p_context_new((uint8_t const *)input, strlen(input));
|
||||
assert_eq(P_SUCCESS, p_parse(context));
|
||||
start = p_result(context);
|
||||
assert(start.pItems().valid());
|
||||
assert(start.pItems().pItem().valid());
|
||||
assert(start.pItems().pItem().pDual().valid());
|
||||
assert(start.pItems().pItem().pDual().pTwo1().valid());
|
||||
assert(start.pItems().pItem().pDual().pOne2().valid());
|
||||
assert(!start.pItems().pItem().pDual().pTwo2().valid());
|
||||
assert(!start.pItems().pItem().pDual().pOne1().valid());
|
||||
|
||||
p_context_delete(context);
|
||||
|
||||
return 0;
|
||||
}
|
||||
+27
-27
@@ -12,51 +12,51 @@ unittest
|
||||
string input = "a, ((b)), b";
|
||||
p_context_t * context = p_context_new(input);
|
||||
assert_eq(P_SUCCESS, p_parse(context));
|
||||
Start * start = p_result(context);
|
||||
assert(start.pItems1 !is null);
|
||||
assert(start.pItems !is null);
|
||||
Items * items = start.pItems;
|
||||
assert(items.pItem !is null);
|
||||
assert(items.pItem.pToken1 !is null);
|
||||
Start start = p_result(context);
|
||||
assert(start.pItems1.valid);
|
||||
assert(start.pItems.valid);
|
||||
Items items = start.pItems;
|
||||
assert(items.pItem.valid);
|
||||
assert(items.pItem.pToken1.valid);
|
||||
assert_eq(TOKEN_a, items.pItem.pToken1.token);
|
||||
assert_eq(11, items.pItem.pToken1.pvalue);
|
||||
assert(items.pItemsMore !is null);
|
||||
ItemsMore * itemsmore = items.pItemsMore;
|
||||
assert(itemsmore.pItem !is null);
|
||||
assert(itemsmore.pItem.pItem !is null);
|
||||
assert(itemsmore.pItem.pItem.pItem !is null);
|
||||
assert(itemsmore.pItem.pItem.pItem.pToken1 !is null);
|
||||
assert(items.pItemsMore.valid);
|
||||
ItemsMore itemsmore = items.pItemsMore;
|
||||
assert(itemsmore.pItem.valid);
|
||||
assert(itemsmore.pItem.pItem.valid);
|
||||
assert(itemsmore.pItem.pItem.pItem.valid);
|
||||
assert(itemsmore.pItem.pItem.pItem.pToken1.valid);
|
||||
assert_eq(TOKEN_b, itemsmore.pItem.pItem.pItem.pToken1.token);
|
||||
assert_eq(22, itemsmore.pItem.pItem.pItem.pToken1.pvalue);
|
||||
assert(itemsmore.pItemsMore !is null);
|
||||
assert(itemsmore.pItemsMore.valid);
|
||||
itemsmore = itemsmore.pItemsMore;
|
||||
assert(itemsmore.pItem !is null);
|
||||
assert(itemsmore.pItem.pToken1 !is null);
|
||||
assert(itemsmore.pItem.valid);
|
||||
assert(itemsmore.pItem.pToken1.valid);
|
||||
assert_eq(TOKEN_b, itemsmore.pItem.pToken1.token);
|
||||
assert_eq(22, itemsmore.pItem.pToken1.pvalue);
|
||||
assert(itemsmore.pItemsMore is null);
|
||||
assert(!itemsmore.pItemsMore.valid);
|
||||
|
||||
p_tree_delete(start);
|
||||
p_context_delete(context);
|
||||
|
||||
input = "";
|
||||
context = p_context_new(input);
|
||||
assert_eq(P_SUCCESS, p_parse(context));
|
||||
start = p_result(context);
|
||||
assert(start.pItems is null);
|
||||
assert(!start.pItems.valid);
|
||||
|
||||
p_tree_delete(start);
|
||||
p_context_delete(context);
|
||||
|
||||
input = "2 1";
|
||||
context = p_context_new(input);
|
||||
assert_eq(P_SUCCESS, p_parse(context));
|
||||
start = p_result(context);
|
||||
assert(start.pItems !is null);
|
||||
assert(start.pItems.pItem !is null);
|
||||
assert(start.pItems.pItem.pDual !is null);
|
||||
assert(start.pItems.pItem.pDual.pTwo1 !is null);
|
||||
assert(start.pItems.pItem.pDual.pOne2 !is null);
|
||||
assert(start.pItems.pItem.pDual.pTwo2 is null);
|
||||
assert(start.pItems.pItem.pDual.pOne1 is null);
|
||||
assert(start.pItems.valid);
|
||||
assert(start.pItems.pItem.valid);
|
||||
assert(start.pItems.pItem.pDual.valid);
|
||||
assert(start.pItems.pItem.pDual.pTwo1.valid);
|
||||
assert(start.pItems.pItem.pDual.pOne2.valid);
|
||||
assert(!start.pItems.pItem.pDual.pTwo2.valid);
|
||||
assert(!start.pItems.pItem.pDual.pOne1.valid);
|
||||
|
||||
p_tree_delete(start);
|
||||
p_context_delete(context);
|
||||
}
|
||||
@@ -9,12 +9,11 @@ int main()
|
||||
p_context_t * context;
|
||||
context = p_context_new((uint8_t const *)input, strlen(input));
|
||||
assert_eq(P_SUCCESS, p_parse(context));
|
||||
Start * start = p_result(context);
|
||||
assert(start->a != NULL);
|
||||
assert(*start->a->pvalue == 1);
|
||||
assert(start->b != NULL);
|
||||
assert(*start->b->pvalue == 2);
|
||||
Start start = p_result(context);
|
||||
assert(p_node_valid(p_Start_a(start)));
|
||||
assert(*p_tree_walk_Start(start, a, pvalue) == 1);
|
||||
assert(p_node_valid(p_Start_b(start)));
|
||||
assert(*p_tree_walk_Start(start, b, pvalue) == 2);
|
||||
|
||||
p_tree_delete(start);
|
||||
p_context_delete(context);
|
||||
}
|
||||
@@ -9,13 +9,12 @@ int main()
|
||||
p_context_t * context;
|
||||
context = p_context_new((uint8_t const *)input, strlen(input));
|
||||
assert(p_parse(context) == P_SUCCESS);
|
||||
Start * start = p_result(context);
|
||||
Start start = p_result(context);
|
||||
|
||||
assert_eq(TOKEN_a, start->first->pToken->token);
|
||||
assert_eq(TOKEN_b, start->second->pToken->token);
|
||||
assert_eq(TOKEN_c, start->third->pToken->token);
|
||||
assert_eq(TOKEN_a, p_tree_walk_Start(start, first, pToken, token));
|
||||
assert_eq(TOKEN_b, p_tree_walk_Start(start, second, pToken, token));
|
||||
assert_eq(TOKEN_c, p_tree_walk_Start(start, third, pToken, token));
|
||||
|
||||
p_tree_delete(start);
|
||||
p_context_delete(context);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -12,11 +12,11 @@ unittest
|
||||
string input = "\na\nb\nc";
|
||||
p_context_t * context = p_context_new(input);
|
||||
assert(p_parse(context) == P_SUCCESS);
|
||||
Start * start = p_result(context);
|
||||
Start start = p_result(context);
|
||||
|
||||
assert_eq(TOKEN_a, start.first.pToken.token);
|
||||
assert_eq(TOKEN_b, start.second.pToken.token);
|
||||
assert_eq(TOKEN_c, start.third.pToken.token);
|
||||
|
||||
p_tree_delete(start);
|
||||
p_context_delete(context);
|
||||
}
|
||||
@@ -9,105 +9,113 @@ int main()
|
||||
p_context_t * context;
|
||||
context = p_context_new((uint8_t const *)input, strlen(input));
|
||||
assert(p_parse(context) == P_SUCCESS);
|
||||
Start * start = p_result(context);
|
||||
Start start = p_result(context);
|
||||
T t1 = p_Start_pT1(start);
|
||||
Token k1 = p_T_pToken(t1);
|
||||
A a1 = p_T_pA(t1);
|
||||
|
||||
assert_eq(2, start->pT1->pToken->position.row);
|
||||
assert_eq(1, start->pT1->pToken->position.col);
|
||||
assert_eq(2, start->pT1->pToken->end_position.row);
|
||||
assert_eq(1, start->pT1->pToken->end_position.col);
|
||||
assert(p_position_valid(start->pT1->pA->position));
|
||||
assert_eq(3, start->pT1->pA->position.row);
|
||||
assert_eq(3, start->pT1->pA->position.col);
|
||||
assert_eq(3, start->pT1->pA->end_position.row);
|
||||
assert_eq(8, start->pT1->pA->end_position.col);
|
||||
assert_eq(2, start->pT1->position.row);
|
||||
assert_eq(1, start->pT1->position.col);
|
||||
assert_eq(3, start->pT1->end_position.row);
|
||||
assert_eq(8, start->pT1->end_position.col);
|
||||
assert_eq(2, p_node_position(k1).row);
|
||||
assert_eq(1, p_node_position(k1).col);
|
||||
assert_eq(2, p_node_end_position(k1).row);
|
||||
assert_eq(1, p_node_end_position(k1).col);
|
||||
assert(p_position_valid(p_node_position(a1)));
|
||||
assert_eq(3, p_node_position(a1).row);
|
||||
assert_eq(3, p_node_position(a1).col);
|
||||
assert_eq(3, p_node_end_position(a1).row);
|
||||
assert_eq(8, p_node_end_position(a1).col);
|
||||
assert_eq(2, p_node_position(t1).row);
|
||||
assert_eq(1, p_node_position(t1).col);
|
||||
assert_eq(3, p_node_end_position(t1).row);
|
||||
assert_eq(8, p_node_end_position(t1).col);
|
||||
|
||||
assert_eq(2, start->position.row);
|
||||
assert_eq(1, start->position.col);
|
||||
assert_eq(3, start->end_position.row);
|
||||
assert_eq(8, start->end_position.col);
|
||||
assert_eq(2, p_node_position(start).row);
|
||||
assert_eq(1, p_node_position(start).col);
|
||||
assert_eq(3, p_node_end_position(start).row);
|
||||
assert_eq(8, p_node_end_position(start).col);
|
||||
|
||||
p_tree_delete(start);
|
||||
p_context_delete(context);
|
||||
|
||||
input = "a\nbb";
|
||||
context = p_context_new((uint8_t const *)input, strlen(input));
|
||||
assert(p_parse(context) == P_SUCCESS);
|
||||
start = p_result(context);
|
||||
t1 = p_Start_pT1(start);
|
||||
k1 = p_T_pToken(t1);
|
||||
a1 = p_T_pA(t1);
|
||||
|
||||
assert_eq(1, start->pT1->pToken->position.row);
|
||||
assert_eq(1, start->pT1->pToken->position.col);
|
||||
assert_eq(1, start->pT1->pToken->end_position.row);
|
||||
assert_eq(1, start->pT1->pToken->end_position.col);
|
||||
assert(p_position_valid(start->pT1->pA->position));
|
||||
assert_eq(2, start->pT1->pA->position.row);
|
||||
assert_eq(1, start->pT1->pA->position.col);
|
||||
assert_eq(2, start->pT1->pA->end_position.row);
|
||||
assert_eq(2, start->pT1->pA->end_position.col);
|
||||
assert_eq(1, start->pT1->position.row);
|
||||
assert_eq(1, start->pT1->position.col);
|
||||
assert_eq(2, start->pT1->end_position.row);
|
||||
assert_eq(2, start->pT1->end_position.col);
|
||||
assert_eq(1, p_node_position(k1).row);
|
||||
assert_eq(1, p_node_position(k1).col);
|
||||
assert_eq(1, p_node_end_position(k1).row);
|
||||
assert_eq(1, p_node_end_position(k1).col);
|
||||
assert(p_position_valid(p_node_position(a1)));
|
||||
assert_eq(2, p_node_position(a1).row);
|
||||
assert_eq(1, p_node_position(a1).col);
|
||||
assert_eq(2, p_node_end_position(a1).row);
|
||||
assert_eq(2, p_node_end_position(a1).col);
|
||||
assert_eq(1, p_node_position(t1).row);
|
||||
assert_eq(1, p_node_position(t1).col);
|
||||
assert_eq(2, p_node_end_position(t1).row);
|
||||
assert_eq(2, p_node_end_position(t1).col);
|
||||
|
||||
assert_eq(1, start->position.row);
|
||||
assert_eq(1, start->position.col);
|
||||
assert_eq(2, start->end_position.row);
|
||||
assert_eq(2, start->end_position.col);
|
||||
assert_eq(1, p_node_position(start).row);
|
||||
assert_eq(1, p_node_position(start).col);
|
||||
assert_eq(2, p_node_end_position(start).row);
|
||||
assert_eq(2, p_node_end_position(start).col);
|
||||
|
||||
p_tree_delete(start);
|
||||
p_context_delete(context);
|
||||
|
||||
input = "a\nc\nc";
|
||||
context = p_context_new((uint8_t const *)input, strlen(input));
|
||||
assert(p_parse(context) == P_SUCCESS);
|
||||
start = p_result(context);
|
||||
t1 = p_Start_pT1(start);
|
||||
k1 = p_T_pToken(t1);
|
||||
a1 = p_T_pA(t1);
|
||||
|
||||
assert_eq(1, start->pT1->pToken->position.row);
|
||||
assert_eq(1, start->pT1->pToken->position.col);
|
||||
assert_eq(1, start->pT1->pToken->end_position.row);
|
||||
assert_eq(1, start->pT1->pToken->end_position.col);
|
||||
assert(p_position_valid(start->pT1->pA->position));
|
||||
assert_eq(2, start->pT1->pA->position.row);
|
||||
assert_eq(1, start->pT1->pA->position.col);
|
||||
assert_eq(3, start->pT1->pA->end_position.row);
|
||||
assert_eq(1, start->pT1->pA->end_position.col);
|
||||
assert_eq(1, start->pT1->position.row);
|
||||
assert_eq(1, start->pT1->position.col);
|
||||
assert_eq(3, start->pT1->end_position.row);
|
||||
assert_eq(1, start->pT1->end_position.col);
|
||||
assert_eq(1, p_node_position(k1).row);
|
||||
assert_eq(1, p_node_position(k1).col);
|
||||
assert_eq(1, p_node_end_position(k1).row);
|
||||
assert_eq(1, p_node_end_position(k1).col);
|
||||
assert(p_position_valid(p_node_position(a1)));
|
||||
assert_eq(2, p_node_position(a1).row);
|
||||
assert_eq(1, p_node_position(a1).col);
|
||||
assert_eq(3, p_node_end_position(a1).row);
|
||||
assert_eq(1, p_node_end_position(a1).col);
|
||||
assert_eq(1, p_node_position(t1).row);
|
||||
assert_eq(1, p_node_position(t1).col);
|
||||
assert_eq(3, p_node_end_position(t1).row);
|
||||
assert_eq(1, p_node_end_position(t1).col);
|
||||
|
||||
assert_eq(1, start->position.row);
|
||||
assert_eq(1, start->position.col);
|
||||
assert_eq(3, start->end_position.row);
|
||||
assert_eq(1, start->end_position.col);
|
||||
assert_eq(1, p_node_position(start).row);
|
||||
assert_eq(1, p_node_position(start).col);
|
||||
assert_eq(3, p_node_end_position(start).row);
|
||||
assert_eq(1, p_node_end_position(start).col);
|
||||
|
||||
p_tree_delete(start);
|
||||
p_context_delete(context);
|
||||
|
||||
input = "a";
|
||||
context = p_context_new((uint8_t const *)input, strlen(input));
|
||||
assert(p_parse(context) == P_SUCCESS);
|
||||
start = p_result(context);
|
||||
t1 = p_Start_pT1(start);
|
||||
k1 = p_T_pToken(t1);
|
||||
a1 = p_T_pA(t1);
|
||||
|
||||
assert_eq(1, start->pT1->pToken->position.row);
|
||||
assert_eq(1, start->pT1->pToken->position.col);
|
||||
assert_eq(1, start->pT1->pToken->end_position.row);
|
||||
assert_eq(1, start->pT1->pToken->end_position.col);
|
||||
assert(!p_position_valid(start->pT1->pA->position));
|
||||
assert_eq(1, start->pT1->position.row);
|
||||
assert_eq(1, start->pT1->position.col);
|
||||
assert_eq(1, start->pT1->end_position.row);
|
||||
assert_eq(1, start->pT1->end_position.col);
|
||||
assert_eq(1, p_node_position(k1).row);
|
||||
assert_eq(1, p_node_position(k1).col);
|
||||
assert_eq(1, p_node_end_position(k1).row);
|
||||
assert_eq(1, p_node_end_position(k1).col);
|
||||
assert(!p_position_valid(p_node_position(a1)));
|
||||
assert_eq(1, p_node_position(t1).row);
|
||||
assert_eq(1, p_node_position(t1).col);
|
||||
assert_eq(1, p_node_end_position(t1).row);
|
||||
assert_eq(1, p_node_end_position(t1).col);
|
||||
|
||||
assert_eq(1, start->position.row);
|
||||
assert_eq(1, start->position.col);
|
||||
assert_eq(1, start->end_position.row);
|
||||
assert_eq(1, start->end_position.col);
|
||||
assert_eq(1, p_node_position(start).row);
|
||||
assert_eq(1, p_node_position(start).col);
|
||||
assert_eq(1, p_node_end_position(start).row);
|
||||
assert_eq(1, p_node_end_position(start).col);
|
||||
|
||||
p_tree_delete(start);
|
||||
p_context_delete(context);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -12,7 +12,7 @@ unittest
|
||||
string input = "\na\n bb ccc";
|
||||
p_context_t * context = p_context_new(input);
|
||||
assert(p_parse(context) == P_SUCCESS);
|
||||
Start * start = p_result(context);
|
||||
Start start = p_result(context);
|
||||
|
||||
assert_eq(2, start.pT1.pToken.position.row);
|
||||
assert_eq(1, start.pT1.pToken.position.col);
|
||||
@@ -33,7 +33,7 @@ unittest
|
||||
assert_eq(3, start.end_position.row);
|
||||
assert_eq(8, start.end_position.col);
|
||||
|
||||
p_tree_delete(start);
|
||||
p_context_delete(context);
|
||||
|
||||
input = "a\nbb";
|
||||
context = p_context_new(input);
|
||||
@@ -59,7 +59,7 @@ unittest
|
||||
assert_eq(2, start.end_position.row);
|
||||
assert_eq(2, start.end_position.col);
|
||||
|
||||
p_tree_delete(start);
|
||||
p_context_delete(context);
|
||||
|
||||
input = "a\nc\nc";
|
||||
context = p_context_new(input);
|
||||
@@ -85,7 +85,7 @@ unittest
|
||||
assert_eq(3, start.end_position.row);
|
||||
assert_eq(1, start.end_position.col);
|
||||
|
||||
p_tree_delete(start);
|
||||
p_context_delete(context);
|
||||
|
||||
input = "a";
|
||||
context = p_context_new(input);
|
||||
@@ -107,5 +107,5 @@ unittest
|
||||
assert_eq(1, start.end_position.row);
|
||||
assert_eq(1, start.end_position.col);
|
||||
|
||||
p_tree_delete(start);
|
||||
p_context_delete(context);
|
||||
}
|
||||
@@ -373,46 +373,45 @@ int main(int argc, char * argv[])
|
||||
context = p_context_new((const uint8_t *)input, strlen(input));
|
||||
size_t result = p_parse(context);
|
||||
assert_eq(P_SUCCESS, result);
|
||||
PModule * pmod = p_result(context);
|
||||
PModuleItems * pmis = pmod->pModuleItems;
|
||||
PFunctionDefinition ** pfds;
|
||||
PModule pmod = p_result(context);
|
||||
PModuleItems pmis = p_PModule_pModuleItems(pmod);
|
||||
PFunctionDefinition * pfds;
|
||||
size_t n_pfds = 0u;
|
||||
while (pmis != NULL)
|
||||
while (p_node_valid(pmis))
|
||||
{
|
||||
PModuleItem * pmi = pmis->pModuleItem;
|
||||
if (pmi->pFunctionDefinition != NULL)
|
||||
PModuleItem pmi = p_PModuleItems_pModuleItem(pmis);
|
||||
if (p_node_valid(p_PModuleItem_pFunctionDefinition(pmi)))
|
||||
{
|
||||
n_pfds++;
|
||||
}
|
||||
pmis = pmis->pModuleItems;
|
||||
pmis = p_PModuleItems_pModuleItems(pmis);
|
||||
}
|
||||
pfds = (PFunctionDefinition **)malloc(n_pfds * sizeof(PModuleItems *));
|
||||
pmis = pmod->pModuleItems;
|
||||
pfds = (PFunctionDefinition *)malloc(n_pfds * sizeof(PFunctionDefinition));
|
||||
pmis = p_PModule_pModuleItems(pmod);
|
||||
size_t pfd_i = n_pfds;
|
||||
while (pmis != NULL)
|
||||
while (p_node_valid(pmis))
|
||||
{
|
||||
PModuleItem * pmi = pmis->pModuleItem;
|
||||
PFunctionDefinition * pfd = pmi->pFunctionDefinition;
|
||||
if (pfd != NULL)
|
||||
PModuleItem pmi = p_PModuleItems_pModuleItem(pmis);
|
||||
PFunctionDefinition pfd = p_PModuleItem_pFunctionDefinition(pmi);
|
||||
if (p_node_valid(pfd))
|
||||
{
|
||||
pfd_i--;
|
||||
assert(pfd_i < n_pfds);
|
||||
pfds[pfd_i] = pfd;
|
||||
}
|
||||
pmis = pmis->pModuleItems;
|
||||
pmis = p_PModuleItems_pModuleItems(pmis);
|
||||
}
|
||||
assert_eq(51, n_pfds);
|
||||
for (size_t i = 0; i < n_pfds; i++)
|
||||
{
|
||||
if (strncmp(expected[i].name, (const char *)pfds[i]->name->pvalue.s, strlen(expected[i].name)) != 0 ||
|
||||
(expected[i].token != pfds[i]->returntype->pType->pTypeBase->pToken1->token))
|
||||
if (strncmp(expected[i].name, (const char *)p_node_data(p_PFunctionDefinition_name(pfds[i]))->pvalue.s, strlen(expected[i].name)) != 0 ||
|
||||
(expected[i].token != p_tree_walk_PFunctionDefinition(pfds[i], returntype, pType, pTypeBase, pToken1, token)))
|
||||
{
|
||||
fprintf(stderr, "Index %lu: expected %s/%u, got %u\n", i, expected[i].name, expected[i].token, pfds[i]->returntype->pType->pTypeBase->pToken1->token);
|
||||
fprintf(stderr, "Index %lu: expected %s/%u, got %u\n", i, expected[i].name, expected[i].token, p_tree_walk_PFunctionDefinition(pfds[i], returntype, pType, pTypeBase, pToken1, token));
|
||||
}
|
||||
}
|
||||
|
||||
free(pfds);
|
||||
p_tree_delete(pmod);
|
||||
p_context_delete(context);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -378,19 +378,19 @@ def main() -> int
|
||||
context = p_context_new(input);
|
||||
size_t result = p_parse(context);
|
||||
assert_eq(P_SUCCESS, result);
|
||||
PModule * pmod = p_result(context);
|
||||
PModuleItems * pmis = pmod.pModuleItems;
|
||||
PFunctionDefinition *[] pfds;
|
||||
while (pmis !is null)
|
||||
PModule pmod = p_result(context);
|
||||
PModuleItems pmis = pmod.pModuleItems;
|
||||
PFunctionDefinition[] pfds;
|
||||
while (pmis.valid)
|
||||
{
|
||||
PModuleItem * pmi = pmis.pModuleItem;
|
||||
if (pmi is null)
|
||||
PModuleItem pmi = pmis.pModuleItem;
|
||||
if (!pmi.valid)
|
||||
{
|
||||
stderr.writeln("pmi is null!!!?");
|
||||
assert(0);
|
||||
}
|
||||
PFunctionDefinition * pfd = pmi.pFunctionDefinition;
|
||||
if (pfd !is null)
|
||||
PFunctionDefinition pfd = pmi.pFunctionDefinition;
|
||||
if (pfd.valid)
|
||||
{
|
||||
pfds = [pfd] ~ pfds;
|
||||
}
|
||||
@@ -405,5 +405,5 @@ def main() -> int
|
||||
stderr.writeln("Index ", i, ": expected ", expected[i].name, "/", expected[i].token, ", got ", pfds[i].name.pvalue.s, "/", pfds[i].returntype.pType.pTypeBase.pToken1.token);
|
||||
}
|
||||
}
|
||||
p_tree_delete(pmod);
|
||||
p_context_delete(context);
|
||||
}
|
||||
+31
-34
@@ -9,55 +9,52 @@ int main()
|
||||
p_context_t * context;
|
||||
context = p_context_new((uint8_t const *)input, strlen(input));
|
||||
assert_eq(P_SUCCESS, p_parse(context));
|
||||
PStartS * start = p_result(context);
|
||||
assert(start->pItems1 != NULL);
|
||||
assert(start->pItems != NULL);
|
||||
PItemsS * items = start->pItems;
|
||||
assert(items->pItem != NULL);
|
||||
assert(items->pItem->pToken1 != NULL);
|
||||
assert_eq(TOKEN_a, items->pItem->pToken1->token);
|
||||
assert_eq(11, items->pItem->pToken1->pvalue);
|
||||
assert(items->pItemsMore != NULL);
|
||||
PItemsMoreS * itemsmore = items->pItemsMore;
|
||||
assert(itemsmore->pItem != NULL);
|
||||
assert(itemsmore->pItem->pItem != NULL);
|
||||
assert(itemsmore->pItem->pItem->pItem != NULL);
|
||||
assert(itemsmore->pItem->pItem->pItem->pToken1 != NULL);
|
||||
assert_eq(TOKEN_b, itemsmore->pItem->pItem->pItem->pToken1->token);
|
||||
assert_eq(22, itemsmore->pItem->pItem->pItem->pToken1->pvalue);
|
||||
assert(itemsmore->pItemsMore != NULL);
|
||||
itemsmore = itemsmore->pItemsMore;
|
||||
assert(itemsmore->pItem != NULL);
|
||||
assert(itemsmore->pItem->pToken1 != NULL);
|
||||
assert_eq(TOKEN_b, itemsmore->pItem->pToken1->token);
|
||||
assert_eq(22, itemsmore->pItem->pToken1->pvalue);
|
||||
assert(itemsmore->pItemsMore == NULL);
|
||||
PStartS start = p_result(context);
|
||||
assert(p_node_valid(p_PStartS_pItems1(start)));
|
||||
assert(p_node_valid(p_PStartS_pItems(start)));
|
||||
PItemsS items = p_PStartS_pItems(start);
|
||||
assert(p_node_valid(p_PItemsS_pItem(items)));
|
||||
assert(p_node_valid(p_tree_walk_PItemsS(items, pItem, pToken1)));
|
||||
assert_eq(TOKEN_a, p_tree_walk_PItemsS(items, pItem, pToken1, token));
|
||||
assert_eq(11, p_tree_walk_PItemsS(items, pItem, pToken1, pvalue));
|
||||
assert(p_node_valid(p_PItemsS_pItemsMore(items)));
|
||||
PItemsMoreS itemsmore = p_PItemsS_pItemsMore(items);
|
||||
assert(p_node_valid(p_PItemsMoreS_pItem(itemsmore)));
|
||||
assert(p_node_valid(p_tree_walk_PItemsMoreS(itemsmore, pItem, pItem)));
|
||||
assert(p_node_valid(p_tree_walk_PItemsMoreS(itemsmore, pItem, pItem, pItem)));
|
||||
assert(p_node_valid(p_tree_walk_PItemsMoreS(itemsmore, pItem, pItem, pItem, pToken1)));
|
||||
assert_eq(TOKEN_b, p_tree_walk_PItemsMoreS(itemsmore, pItem, pItem, pItem, pToken1, token));
|
||||
assert_eq(22, p_tree_walk_PItemsMoreS(itemsmore, pItem, pItem, pItem, pToken1, pvalue));
|
||||
assert(p_node_valid(p_PItemsMoreS_pItemsMore(itemsmore)));
|
||||
itemsmore = p_PItemsMoreS_pItemsMore(itemsmore);
|
||||
assert(p_node_valid(p_PItemsMoreS_pItem(itemsmore)));
|
||||
assert(p_node_valid(p_tree_walk_PItemsMoreS(itemsmore, pItem, pToken1)));
|
||||
assert_eq(TOKEN_b, p_tree_walk_PItemsMoreS(itemsmore, pItem, pToken1, token));
|
||||
assert_eq(22, p_tree_walk_PItemsMoreS(itemsmore, pItem, pToken1, pvalue));
|
||||
assert(!p_node_valid(p_PItemsMoreS_pItemsMore(itemsmore)));
|
||||
|
||||
p_tree_delete(start);
|
||||
p_context_delete(context);
|
||||
|
||||
input = "";
|
||||
context = p_context_new((uint8_t const *)input, strlen(input));
|
||||
assert_eq(P_SUCCESS, p_parse(context));
|
||||
start = p_result(context);
|
||||
assert(start->pItems == NULL);
|
||||
assert(!p_node_valid(p_PStartS_pItems(start)));
|
||||
|
||||
p_tree_delete(start);
|
||||
p_context_delete(context);
|
||||
|
||||
input = "2 1";
|
||||
context = p_context_new((uint8_t const *)input, strlen(input));
|
||||
assert_eq(P_SUCCESS, p_parse(context));
|
||||
start = p_result(context);
|
||||
assert(start->pItems != NULL);
|
||||
assert(start->pItems->pItem != NULL);
|
||||
assert(start->pItems->pItem->pDual != NULL);
|
||||
assert(start->pItems->pItem->pDual->pTwo1 != NULL);
|
||||
assert(start->pItems->pItem->pDual->pOne2 != NULL);
|
||||
assert(start->pItems->pItem->pDual->pTwo2 == NULL);
|
||||
assert(start->pItems->pItem->pDual->pOne1 == NULL);
|
||||
assert(p_node_valid(p_PStartS_pItems(start)));
|
||||
assert(p_node_valid(p_tree_walk_PStartS(start, pItems, pItem)));
|
||||
assert(p_node_valid(p_tree_walk_PStartS(start, pItems, pItem, pDual)));
|
||||
assert(p_node_valid(p_tree_walk_PStartS(start, pItems, pItem, pDual, pTwo1)));
|
||||
assert(p_node_valid(p_tree_walk_PStartS(start, pItems, pItem, pDual, pOne2)));
|
||||
assert(!p_node_valid(p_tree_walk_PStartS(start, pItems, pItem, pDual, pTwo2)));
|
||||
assert(!p_node_valid(p_tree_walk_PStartS(start, pItems, pItem, pDual, pOne1)));
|
||||
|
||||
p_tree_delete(start);
|
||||
p_context_delete(context);
|
||||
|
||||
return 0;
|
||||
|
||||
+27
-27
@@ -12,51 +12,51 @@ unittest
|
||||
string input = "a, ((b)), b";
|
||||
p_context_t * context = p_context_new(input);
|
||||
assert_eq(P_SUCCESS, p_parse(context));
|
||||
PStartS * start = p_result(context);
|
||||
assert(start.pItems1 !is null);
|
||||
assert(start.pItems !is null);
|
||||
PItemsS * items = start.pItems;
|
||||
assert(items.pItem !is null);
|
||||
assert(items.pItem.pToken1 !is null);
|
||||
PStartS start = p_result(context);
|
||||
assert(start.pItems1.valid);
|
||||
assert(start.pItems.valid);
|
||||
PItemsS items = start.pItems;
|
||||
assert(items.pItem.valid);
|
||||
assert(items.pItem.pToken1.valid);
|
||||
assert_eq(TOKEN_a, items.pItem.pToken1.token);
|
||||
assert_eq(11, items.pItem.pToken1.pvalue);
|
||||
assert(items.pItemsMore !is null);
|
||||
PItemsMoreS * itemsmore = items.pItemsMore;
|
||||
assert(itemsmore.pItem !is null);
|
||||
assert(itemsmore.pItem.pItem !is null);
|
||||
assert(itemsmore.pItem.pItem.pItem !is null);
|
||||
assert(itemsmore.pItem.pItem.pItem.pToken1 !is null);
|
||||
assert(items.pItemsMore.valid);
|
||||
PItemsMoreS itemsmore = items.pItemsMore;
|
||||
assert(itemsmore.pItem.valid);
|
||||
assert(itemsmore.pItem.pItem.valid);
|
||||
assert(itemsmore.pItem.pItem.pItem.valid);
|
||||
assert(itemsmore.pItem.pItem.pItem.pToken1.valid);
|
||||
assert_eq(TOKEN_b, itemsmore.pItem.pItem.pItem.pToken1.token);
|
||||
assert_eq(22, itemsmore.pItem.pItem.pItem.pToken1.pvalue);
|
||||
assert(itemsmore.pItemsMore !is null);
|
||||
assert(itemsmore.pItemsMore.valid);
|
||||
itemsmore = itemsmore.pItemsMore;
|
||||
assert(itemsmore.pItem !is null);
|
||||
assert(itemsmore.pItem.pToken1 !is null);
|
||||
assert(itemsmore.pItem.valid);
|
||||
assert(itemsmore.pItem.pToken1.valid);
|
||||
assert_eq(TOKEN_b, itemsmore.pItem.pToken1.token);
|
||||
assert_eq(22, itemsmore.pItem.pToken1.pvalue);
|
||||
assert(itemsmore.pItemsMore is null);
|
||||
assert(!itemsmore.pItemsMore.valid);
|
||||
|
||||
p_tree_delete(start);
|
||||
p_context_delete(context);
|
||||
|
||||
input = "";
|
||||
context = p_context_new(input);
|
||||
assert_eq(P_SUCCESS, p_parse(context));
|
||||
start = p_result(context);
|
||||
assert(start.pItems is null);
|
||||
assert(!start.pItems.valid);
|
||||
|
||||
p_tree_delete(start);
|
||||
p_context_delete(context);
|
||||
|
||||
input = "2 1";
|
||||
context = p_context_new(input);
|
||||
assert_eq(P_SUCCESS, p_parse(context));
|
||||
start = p_result(context);
|
||||
assert(start.pItems !is null);
|
||||
assert(start.pItems.pItem !is null);
|
||||
assert(start.pItems.pItem.pDual !is null);
|
||||
assert(start.pItems.pItem.pDual.pTwo1 !is null);
|
||||
assert(start.pItems.pItem.pDual.pOne2 !is null);
|
||||
assert(start.pItems.pItem.pDual.pTwo2 is null);
|
||||
assert(start.pItems.pItem.pDual.pOne1 is null);
|
||||
assert(start.pItems.valid);
|
||||
assert(start.pItems.pItem.valid);
|
||||
assert(start.pItems.pItem.pDual.valid);
|
||||
assert(start.pItems.pItem.pDual.pTwo1.valid);
|
||||
assert(start.pItems.pItem.pDual.pOne2.valid);
|
||||
assert(!start.pItems.pItem.pDual.pTwo2.valid);
|
||||
assert(!start.pItems.pItem.pDual.pOne1.valid);
|
||||
|
||||
p_tree_delete(start);
|
||||
p_context_delete(context);
|
||||
}
|
||||
@@ -9,81 +9,91 @@ int main()
|
||||
p_context_t * context;
|
||||
context = p_context_new((uint8_t const *)input, strlen(input));
|
||||
assert(p_parse(context) == P_SUCCESS);
|
||||
Start * start = p_result(context);
|
||||
Start start = p_result(context);
|
||||
T t1 = p_Start_pT1(start);
|
||||
T t2 = p_Start_pT2(start);
|
||||
T t3 = p_Start_pT3(start);
|
||||
Token k1 = p_T_pToken(t1);
|
||||
Token k2 = p_T_pToken(t2);
|
||||
Token k3 = p_T_pToken(t3);
|
||||
|
||||
assert_eq(1, start->pT1->pToken->position.row);
|
||||
assert_eq(1, start->pT1->pToken->position.col);
|
||||
assert_eq(1, start->pT1->pToken->end_position.row);
|
||||
assert_eq(1, start->pT1->pToken->end_position.col);
|
||||
assert_eq(1, start->pT1->position.row);
|
||||
assert_eq(1, start->pT1->position.col);
|
||||
assert_eq(1, start->pT1->end_position.row);
|
||||
assert_eq(1, start->pT1->end_position.col);
|
||||
assert_eq(1, p_node_position(k1).row);
|
||||
assert_eq(1, p_node_position(k1).col);
|
||||
assert_eq(1, p_node_end_position(k1).row);
|
||||
assert_eq(1, p_node_end_position(k1).col);
|
||||
assert_eq(1, p_node_position(t1).row);
|
||||
assert_eq(1, p_node_position(t1).col);
|
||||
assert_eq(1, p_node_end_position(t1).row);
|
||||
assert_eq(1, p_node_end_position(t1).col);
|
||||
|
||||
assert_eq(1, start->pT2->pToken->position.row);
|
||||
assert_eq(2, start->pT2->pToken->position.col);
|
||||
assert_eq(1, start->pT2->pToken->end_position.row);
|
||||
assert_eq(3, start->pT2->pToken->end_position.col);
|
||||
assert_eq(1, start->pT2->position.row);
|
||||
assert_eq(2, start->pT2->position.col);
|
||||
assert_eq(1, start->pT2->end_position.row);
|
||||
assert_eq(3, start->pT2->end_position.col);
|
||||
assert_eq(1, p_node_position(k2).row);
|
||||
assert_eq(2, p_node_position(k2).col);
|
||||
assert_eq(1, p_node_end_position(k2).row);
|
||||
assert_eq(3, p_node_end_position(k2).col);
|
||||
assert_eq(1, p_node_position(t2).row);
|
||||
assert_eq(2, p_node_position(t2).col);
|
||||
assert_eq(1, p_node_end_position(t2).row);
|
||||
assert_eq(3, p_node_end_position(t2).col);
|
||||
|
||||
assert_eq(1, start->pT3->pToken->position.row);
|
||||
assert_eq(4, start->pT3->pToken->position.col);
|
||||
assert_eq(1, start->pT3->pToken->end_position.row);
|
||||
assert_eq(6, start->pT3->pToken->end_position.col);
|
||||
assert_eq(1, start->pT3->position.row);
|
||||
assert_eq(4, start->pT3->position.col);
|
||||
assert_eq(1, start->pT3->end_position.row);
|
||||
assert_eq(6, start->pT3->end_position.col);
|
||||
assert_eq(1, p_node_position(k3).row);
|
||||
assert_eq(4, p_node_position(k3).col);
|
||||
assert_eq(1, p_node_end_position(k3).row);
|
||||
assert_eq(6, p_node_end_position(k3).col);
|
||||
assert_eq(1, p_node_position(t3).row);
|
||||
assert_eq(4, p_node_position(t3).col);
|
||||
assert_eq(1, p_node_end_position(t3).row);
|
||||
assert_eq(6, p_node_end_position(t3).col);
|
||||
|
||||
assert_eq(1, start->position.row);
|
||||
assert_eq(1, start->position.col);
|
||||
assert_eq(1, start->end_position.row);
|
||||
assert_eq(6, start->end_position.col);
|
||||
assert_eq(1, p_node_position(start).row);
|
||||
assert_eq(1, p_node_position(start).col);
|
||||
assert_eq(1, p_node_end_position(start).row);
|
||||
assert_eq(6, p_node_end_position(start).col);
|
||||
|
||||
p_tree_delete(start);
|
||||
p_context_delete(context);
|
||||
|
||||
input = "\n\n bb\nc\ncc\n\n a";
|
||||
context = p_context_new((uint8_t const *)input, strlen(input));
|
||||
assert(p_parse(context) == P_SUCCESS);
|
||||
start = p_result(context);
|
||||
t1 = p_Start_pT1(start);
|
||||
t2 = p_Start_pT2(start);
|
||||
t3 = p_Start_pT3(start);
|
||||
k1 = p_T_pToken(t1);
|
||||
k2 = p_T_pToken(t2);
|
||||
k3 = p_T_pToken(t3);
|
||||
|
||||
assert_eq(3, start->pT1->pToken->position.row);
|
||||
assert_eq(3, start->pT1->pToken->position.col);
|
||||
assert_eq(3, start->pT1->pToken->end_position.row);
|
||||
assert_eq(4, start->pT1->pToken->end_position.col);
|
||||
assert_eq(3, start->pT1->position.row);
|
||||
assert_eq(3, start->pT1->position.col);
|
||||
assert_eq(3, start->pT1->end_position.row);
|
||||
assert_eq(4, start->pT1->end_position.col);
|
||||
assert_eq(3, p_node_position(k1).row);
|
||||
assert_eq(3, p_node_position(k1).col);
|
||||
assert_eq(3, p_node_end_position(k1).row);
|
||||
assert_eq(4, p_node_end_position(k1).col);
|
||||
assert_eq(3, p_node_position(t1).row);
|
||||
assert_eq(3, p_node_position(t1).col);
|
||||
assert_eq(3, p_node_end_position(t1).row);
|
||||
assert_eq(4, p_node_end_position(t1).col);
|
||||
|
||||
assert_eq(4, start->pT2->pToken->position.row);
|
||||
assert_eq(1, start->pT2->pToken->position.col);
|
||||
assert_eq(5, start->pT2->pToken->end_position.row);
|
||||
assert_eq(2, start->pT2->pToken->end_position.col);
|
||||
assert_eq(4, start->pT2->position.row);
|
||||
assert_eq(1, start->pT2->position.col);
|
||||
assert_eq(5, start->pT2->end_position.row);
|
||||
assert_eq(2, start->pT2->end_position.col);
|
||||
assert_eq(4, p_node_position(k2).row);
|
||||
assert_eq(1, p_node_position(k2).col);
|
||||
assert_eq(5, p_node_end_position(k2).row);
|
||||
assert_eq(2, p_node_end_position(k2).col);
|
||||
assert_eq(4, p_node_position(t2).row);
|
||||
assert_eq(1, p_node_position(t2).col);
|
||||
assert_eq(5, p_node_end_position(t2).row);
|
||||
assert_eq(2, p_node_end_position(t2).col);
|
||||
|
||||
assert_eq(7, start->pT3->pToken->position.row);
|
||||
assert_eq(6, start->pT3->pToken->position.col);
|
||||
assert_eq(7, start->pT3->pToken->end_position.row);
|
||||
assert_eq(6, start->pT3->pToken->end_position.col);
|
||||
assert_eq(7, start->pT3->position.row);
|
||||
assert_eq(6, start->pT3->position.col);
|
||||
assert_eq(7, start->pT3->end_position.row);
|
||||
assert_eq(6, start->pT3->end_position.col);
|
||||
assert_eq(7, p_node_position(k3).row);
|
||||
assert_eq(6, p_node_position(k3).col);
|
||||
assert_eq(7, p_node_end_position(k3).row);
|
||||
assert_eq(6, p_node_end_position(k3).col);
|
||||
assert_eq(7, p_node_position(t3).row);
|
||||
assert_eq(6, p_node_position(t3).col);
|
||||
assert_eq(7, p_node_end_position(t3).row);
|
||||
assert_eq(6, p_node_end_position(t3).col);
|
||||
|
||||
assert_eq(3, start->position.row);
|
||||
assert_eq(3, start->position.col);
|
||||
assert_eq(7, start->end_position.row);
|
||||
assert_eq(6, start->end_position.col);
|
||||
assert_eq(3, p_node_position(start).row);
|
||||
assert_eq(3, p_node_position(start).col);
|
||||
assert_eq(7, p_node_end_position(start).row);
|
||||
assert_eq(6, p_node_end_position(start).col);
|
||||
|
||||
p_tree_delete(start);
|
||||
p_context_delete(context);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -12,7 +12,7 @@ unittest
|
||||
string input = "abbccc";
|
||||
p_context_t * context = p_context_new(input);
|
||||
assert(p_parse(context) == P_SUCCESS);
|
||||
Start * start = p_result(context);
|
||||
Start start = p_result(context);
|
||||
|
||||
assert_eq(1, start.pT1.pToken.position.row);
|
||||
assert_eq(1, start.pT1.pToken.position.col);
|
||||
@@ -46,7 +46,7 @@ unittest
|
||||
assert_eq(1, start.end_position.row);
|
||||
assert_eq(6, start.end_position.col);
|
||||
|
||||
p_tree_delete(start);
|
||||
p_context_delete(context);
|
||||
|
||||
input = "\n\n bb\nc\ncc\n\n a";
|
||||
context = p_context_new(input);
|
||||
@@ -85,5 +85,5 @@ unittest
|
||||
assert_eq(7, start.end_position.row);
|
||||
assert_eq(6, start.end_position.col);
|
||||
|
||||
p_tree_delete(start);
|
||||
p_context_delete(context);
|
||||
}
|
||||
Reference in new issue
Block a user