Ресурс, который вы указали, описывает несколько способов анализа YAML. Синтаксический анализ на основе токенов, в отличие от того, что говорится в учебнике, совершенно бесполезен, если вы не используете подсветку синтаксиса. Во всех остальных случаях вы хотите использовать анализ на основе событий. Поэтому я предполагаю, что вы пытались использовать это.
Предоставляет ли libyaml способ поддерживать эти отношения в дереве
Анализ на основе событий делает поддерживая древовидную структуру (не уверен, что именно вы подразумеваете под отношением в дереве ), вы получаете … Start и … End события для последовательностей и отображений, которые описывают структуру ввода. Довольно просто составить список struct Input
, прогуливаясь по потоку событий:
#include <yaml.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <assert.h>
struct Input {
char key[100];
char value[100];
};
struct Input gen(const char *key, const char *value) {
struct Input ret;
strcpy(ret.key, key);
strcpy(ret.value, value);
return ret;
}
void append_all(yaml_parser_t *p, struct Input **target,
char cur_key[100], size_t len) {
yaml_event_t e;
yaml_parser_parse(p, &e);
switch (e.type) {
case YAML_MAPPING_START_EVENT:
yaml_event_delete(&e);
yaml_parser_parse(p, &e);
while (e.type != YAML_MAPPING_END_EVENT) {
// assume scalar key
assert(e.type == YAML_SCALAR_EVENT);
if (len != 0) cur_key[len++] = '.';
memcpy(cur_key + len, e.data.scalar.value,
strlen(e.data.scalar.value) + 1);
const size_t new_len = len + strlen(e.data.scalar.value);
yaml_event_delete(&e);
append_all(p, target, cur_key, new_len);
if (len != 0) --len;
cur_key[len] = '\0'; // remove key part
yaml_parser_parse(p, &e);
}
break;
case YAML_SCALAR_EVENT:
*(*target)++ = gen(cur_key, e.data.scalar.value);
break;
default: assert(false);
}
yaml_event_delete(&e);
}
int main(int argc, char *argv[]) {
yaml_parser_t p;
yaml_event_t e;
yaml_parser_initialize(&p);
FILE *f = fopen("foo.yaml", "r");
yaml_parser_set_input_file(&p, f);
// skip stream start and document start
yaml_parser_parse(&p, &e);
yaml_event_delete(&e);
yaml_parser_parse(&p, &e);
yaml_event_delete(&e);
char cur_key[100] = {'\0'};
struct Input input[100];
struct Input *input_end = input;
append_all(&p, &input_end, cur_key, 0);
// skip document end and stream end
yaml_parser_parse(&p, &e);
yaml_event_delete(&e);
yaml_parser_parse(&p, &e);
yaml_event_delete(&e);
yaml_parser_delete(&p);
fclose(f);
// print out input items
for (struct Input *cur = input; cur < input_end; ++cur) {
printf("%s = %s\n", cur->key, cur->value);
}
}