Skip to content

Commit

Permalink
keep track of non-slashdashed {}
Browse files Browse the repository at this point in the history
fixes #10
  • Loading branch information
tjol committed Dec 8, 2024
1 parent 596424b commit e3763bd
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 3 deletions.
24 changes: 21 additions & 3 deletions src/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ struct _kdl_parser {
kdl_parse_option opt;
int depth;
int slashdash_depth;
int child_block_at_depth;
enum _kdl_parser_state state;
kdl_event_data event;
kdl_owned_string tmp_string_type;
Expand All @@ -73,6 +74,7 @@ static void _init_kdl_parser(kdl_parser* self, kdl_parse_option opt)
{
self->depth = 0;
self->slashdash_depth = -1;
self->child_block_at_depth = -1;
self->state = PARSER_OUTSIDE_NODE;
self->tmp_string_type = (kdl_owned_string){NULL, 0};
self->tmp_string_key = (kdl_owned_string){NULL, 0};
Expand Down Expand Up @@ -408,12 +410,25 @@ static kdl_event_data* _next_node(kdl_parser* self, kdl_token* token)
self->state = PARSER_IN_NODE;
--self->depth;
_reset_event(self);
if (self->slashdash_depth < 0) {
// slashdash is not active, this child block can't be
// followed by another child block.
self->state |= PARSER_FLAG_END_OF_NODE;
self->child_block_at_depth = self->depth;
} else {
// slashdash applies to this child block
if (self->child_block_at_depth == self->depth) {
// we already had a child block here before
self->state |= PARSER_FLAG_END_OF_NODE;
} else {
// all child blocks seen so far in this node have been
// slashdashed
self->state |= PARSER_FLAG_END_OF_NODE_OR_CHILD_BLOCK;
}
}
if (self->slashdash_depth == self->depth + 1) {
// slashdash is ending here
self->slashdash_depth = -1;
self->state |= PARSER_FLAG_END_OF_NODE_OR_CHILD_BLOCK;
} else {
self->state |= PARSER_FLAG_END_OF_NODE;
}
return NULL;
}
Expand Down Expand Up @@ -549,6 +564,9 @@ static kdl_event_data* _next_event_in_node(kdl_parser* self, kdl_token* token)
// end the node
self->state = PARSER_OUTSIDE_NODE;
--self->depth;
if (self->child_block_at_depth > self->depth) {
self->child_block_at_depth = -1;
}
_reset_event(self);
self->event.event = KDL_EVENT_END_NODE;
ev = _apply_slashdash(self);
Expand Down
49 changes: 49 additions & 0 deletions tests/parser_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "test_util.h"

#include <stdio.h>
#include <string.h>

static void test_basics(void)
Expand Down Expand Up @@ -188,6 +189,53 @@ static void test_slashdash(void)
kdl_destroy_parser(parser);
}

static void test_slashdash_child_block(void)
{
kdl_str invalid_docs[] = {
kdl_str_from_cstr("node /-{child} arg"), // arg can't follow child block
kdl_str_from_cstr("node /-{child} /-arg"), // arg can't follow child block
kdl_str_from_cstr("node {child} /-arg"), // arg can't follow child block
kdl_str_from_cstr("node { one } /-{ two } { three }"), // two child blocks
kdl_str_from_cstr("node /-{ one } { two } { three }"), // two child blocks
};
int n_invalid = sizeof(invalid_docs) / sizeof(invalid_docs[0]);

kdl_str valid_docs[] = {
kdl_str_from_cstr("node arg /-{child}"), // child blocks can be slashdashed
kdl_str_from_cstr("node /-arg {child}"), // args can be slashdashed
kdl_str_from_cstr("node /-arg /-{child}"), // multiple slashdashes
kdl_str_from_cstr("node /-{one}/-{two}{three}"), // {} after /-{}
kdl_str_from_cstr("node { one; } /-{ two } /-{ three }"), // /-{} after {}
};
int n_valid = sizeof(valid_docs) / sizeof(valid_docs[0]);

for (int i = 0; i < n_invalid; ++i) {
kdl_parser* parser = kdl_create_string_parser(invalid_docs[i], KDL_READ_VERSION_2);

kdl_event_data* ev;
do {
ev = kdl_parser_next_event(parser);
} while (ev->event != KDL_EVENT_EOF && ev->event != KDL_EVENT_PARSE_ERROR);

ASSERT(ev->event == KDL_EVENT_PARSE_ERROR);

kdl_destroy_parser(parser);
}

for (int i = 0; i < n_valid; ++i) {
kdl_parser* parser = kdl_create_string_parser(valid_docs[i], KDL_READ_VERSION_2);

kdl_event_data* ev;
do {
ev = kdl_parser_next_event(parser);
} while (ev->event != KDL_EVENT_EOF && ev->event != KDL_EVENT_PARSE_ERROR);

ASSERT(ev->event == KDL_EVENT_EOF);

kdl_destroy_parser(parser);
}
}

static void test_unbalanced_brace(void)
{
char const* const kdl_text = "node1 {";
Expand Down Expand Up @@ -278,6 +326,7 @@ void TEST_MAIN(void)
{
run_test("Parser: basics", &test_basics);
run_test("Parser: slashdash", &test_slashdash);
run_test("Parser: slashdash with child blocks", &test_slashdash_child_block);
run_test("Parser: unbalanced {", &test_unbalanced_brace);
run_test("Parser: arg can't be identifier", &test_identifier_arg);
run_test("Parser: type can't be number", &test_number_type);
Expand Down

0 comments on commit e3763bd

Please sign in to comment.