yin parser CHANGE parse known extension subelements correctly WIP
diff --git a/src/parser_yin.c b/src/parser_yin.c
index ab92cc7..3576471 100644
--- a/src/parser_yin.c
+++ b/src/parser_yin.c
@@ -50,6 +50,7 @@
[YIN_ARG_URI] = "uri",
[YIN_ARG_DATE] = "date",
[YIN_ARG_TAG] = "tag",
+ [YIN_ARG_NONE] = "none",
};
enum ly_stmt
@@ -1062,7 +1063,7 @@
};
/* check attributes */
- LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NONE, NULL, Y_STR_ARG, LY_STMT_ERROR_MESSAGE));
+ LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NONE, NULL, Y_MAYBE_STR_ARG, LY_STMT_ERROR_MESSAGE));
return yin_parse_content(ctx, subelems, 2, data, LY_STMT_ERROR_MESSAGE, NULL, exts);
}
@@ -3183,7 +3184,7 @@
/* end of extension instance reached */
break;
}
- LY_CHECK_RET(yin_parse_element_generic(ctx, name, name_len, prefix, prefix_len, data, &new_subelem));
+ LY_CHECK_RET(yin_parse_element_generic(ctx, name, name_len, prefix, prefix_len, LY_STMT_EXTENSION_INSTANCE, data, &new_subelem));
if (!e->child) {
e->child = new_subelem;
} else {
@@ -3210,13 +3211,18 @@
}
LY_ERR
-yin_parse_arg_inext_known(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, enum ly_stmt elem_type, struct lysp_stmt **args)
+yin_parse_arg_inext_known(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, enum ly_stmt elem_type,
+ enum ly_stmt parent, struct lysp_stmt **args)
{
LY_ERR ret = LY_SUCCESS;
struct lysp_stmt *arg;
- (void)data;
+ char *out = NULL;
+ const char *name, *prefix;
+ size_t out_len, name_len, prefix_len;
+ int dynamic;
+ enum ly_stmt child;
- LY_LIST_NEW_GOTO(ctx->xml_ctx.ctx, args, arg, next, ret, cleanup);
+ LY_LIST_NEW_RET(ctx->xml_ctx.ctx, args, arg, next);
switch (elem_type) {
case LY_STMT_ACTION:
@@ -3245,18 +3251,17 @@
case LY_STMT_TYPEDEF:
case LY_STMT_UNITS:
case LY_STMT_USES:
- ret = yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &arg->arg, Y_MAYBE_STR_ARG, elem_type);
+ LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &arg->arg, Y_MAYBE_STR_ARG, elem_type));
break;
case LY_STMT_AUGMENT:
case LY_STMT_DEVIATION:
case LY_STMT_REFINE:
- ret = yin_parse_attribute(ctx, attrs, YIN_ARG_TARGET_NODE, &arg->arg, Y_MAYBE_STR_ARG, elem_type);
+ LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_TARGET_NODE, &arg->arg, Y_MAYBE_STR_ARG, elem_type));
break;
case LY_STMT_CONFIG:
case LY_STMT_DEFAULT:
case LY_STMT_DEVIATE:
case LY_STMT_ERROR_APP_TAG:
- case LY_STMT_ERROR_MESSAGE:
case LY_STMT_FRACTION_DIGITS:
case LY_STMT_KEY:
case LY_STMT_LENGTH:
@@ -3276,53 +3281,65 @@
case LY_STMT_VALUE:
case LY_STMT_YANG_VERSION:
case LY_STMT_YIN_ELEMENT:
- ret = yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &arg->arg, Y_MAYBE_STR_ARG, elem_type);
- break;
- case LY_STMT_CONTACT:
- case LY_STMT_DESCRIPTION:
- case LY_STMT_ORGANIZATION:
- case LY_STMT_REFERENCE:
- ret = yin_parse_attribute(ctx, attrs, YIN_ARG_TEXT, &arg->arg, Y_MAYBE_STR_ARG, elem_type);
+ LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &arg->arg, Y_MAYBE_STR_ARG, elem_type));
break;
case LY_STMT_IMPORT:
case LY_STMT_INCLUDE:
case LY_STMT_BELONGS_TO:
- ret = yin_parse_attribute(ctx, attrs, YIN_ARG_MODULE, &arg->arg, Y_MAYBE_STR_ARG, elem_type);
+ LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_MODULE, &arg->arg, Y_MAYBE_STR_ARG, elem_type));
break;
case LY_STMT_INPUT:
case LY_STMT_OUTPUT:
- ret = yin_parse_attribute(ctx, attrs, YIN_ARG_NONE, &arg->arg, Y_MAYBE_STR_ARG, elem_type);
+ LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NONE, &arg->arg, Y_MAYBE_STR_ARG, elem_type));
break;
case LY_STMT_MUST:
case LY_STMT_WHEN:
- ret = yin_parse_attribute(ctx, attrs, YIN_ARG_CONDITION, &arg->arg, Y_MAYBE_STR_ARG, elem_type);
+ LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_CONDITION, &arg->arg, Y_MAYBE_STR_ARG, elem_type));
break;
case LY_STMT_NAMESPACE:
- ret = yin_parse_attribute(ctx, attrs, YIN_ARG_URI, &arg->arg, Y_MAYBE_STR_ARG, elem_type);
+ LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_URI, &arg->arg, Y_MAYBE_STR_ARG, elem_type));
break;
case LY_STMT_REVISION:
case LY_STMT_REVISION_DATE:
- ret = yin_parse_attribute(ctx, attrs, YIN_ARG_DATE, &arg->arg, Y_MAYBE_STR_ARG, elem_type);
+ LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_DATE, &arg->arg, Y_MAYBE_STR_ARG, elem_type));
break;
case LY_STMT_UNIQUE:
- ret = yin_parse_attribute(ctx, attrs, YIN_ARG_TAG, &arg->arg, Y_MAYBE_STR_ARG, elem_type);
+ LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_TAG, &arg->arg, Y_MAYBE_STR_ARG, elem_type));
break;
- case LY_STMT_ARG_TEXT:
- case LY_STMT_ARG_VALUE:
- // TODO
+ /* argument is mapped to yin element */
+ case LY_STMT_CONTACT:
+ case LY_STMT_DESCRIPTION:
+ case LY_STMT_ORGANIZATION:
+ case LY_STMT_REFERENCE:
+ case LY_STMT_ERROR_MESSAGE:
+ /* there should be no attribute, argument is supposed to be first subelement */
+ LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NONE, &arg->arg, Y_MAYBE_STR_ARG, elem_type));
+ ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
+ /* TODO fix message */
+ LY_CHECK_ERR_RET(ret != LY_EINVAL, LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_FIRT_SUBELEM, ly_stmt2str(elem_type), parent), LY_EVALID);
+ LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
+ child = yin_match_keyword(ctx, name, name_len, prefix, prefix_len, elem_type);
+ if ((elem_type == LY_STMT_ERROR_MESSAGE && child != LY_STMT_ARG_VALUE) || child != LY_STMT_ARG_TEXT) {
+ LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, name_len, name, elem_type);
+ return LY_EVALID;
+ }
+ /* load and save content */
+ LY_CHECK_RET(lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic));
+ INSERT_STRING(ctx->xml_ctx.ctx, arg->arg, dynamic, out, out_len);
+ /* load closing tag */
+ LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
break;
default:
LOGINT(ctx->xml_ctx.ctx);
- ret = LY_EINT;
+ return LY_EINT;
}
-cleanup:
- return ret;
+ return LY_SUCCESS;
}
LY_ERR
-yin_parse_element_generic(struct yin_parser_ctx *ctx, const char *name, size_t name_len, const char *prefix, size_t prefix_len, const char **data,
- struct lysp_stmt **element)
+yin_parse_element_generic(struct yin_parser_ctx *ctx, const char *name, size_t name_len, const char *prefix, size_t prefix_len, enum ly_stmt parent,
+ const char **data, struct lysp_stmt **element)
{
LY_ERR ret = LY_SUCCESS;
const char *temp_prefix, *temp_name;
@@ -3352,40 +3369,9 @@
return LY_EVALID;
} else if ((*element)->kw != LY_STMT_EXTENSION_INSTANCE) {
/* element is known yang keyword, which means argument can be parsed correctly. */
- LY_CHECK_RET(yin_parse_arg_inext_known(ctx, attrs, data, (*element)->kw, &(*element)->child));
+ LY_CHECK_RET(yin_parse_arg_inext_known(ctx, attrs, data, (*element)->kw, parent, &(*element)->child));
} else {
- /* load attributes in generic way- TODO in case of non-extension keyword, the argument details are known,
- * so the argument can be stored correctly instead of storing pure attributes */
- // while(ctx->xml_ctx.status == LYXML_ATTRIBUTE) {
- // /* add new element to linked-list */
- // new = calloc(1, sizeof(*last));
- // LY_CHECK_ERR_RET(!new, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
- // if (!(*element)->child) {
- // /* save first */
- // (*element)->child = new;
- // } else {
- // last->next = new;
- // }
- // last = new;
-
- // last->flags |= LYS_YIN_ATTR;
- // LY_CHECK_RET(lyxml_get_attribute(&ctx->xml_ctx, data, &temp_prefix, &temp_prefix_len, &temp_name, &temp_name_len));
- // last->stmt = lydict_insert(ctx->xml_ctx.ctx, temp_name, temp_name_len);
- // LY_CHECK_RET(!last->stmt, LY_EMEM);
- // last->kw = yin_match_keyword(ctx, temp_name, temp_name_len, temp_prefix, temp_prefix_len, LY_STMT_EXTENSION_INSTANCE);
-
- // LY_CHECK_RET(lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic));
- // /* attributes with prefix are ignored */
- // if (!temp_prefix) {
- // INSERT_STRING(ctx->xml_ctx.ctx, last->arg, dynamic, out, out_len);
- // LY_CHECK_RET(!last->arg, LY_EMEM);
- // } else {
- // if (dynamic) {
- // free(out);
- // }
- // }
- // }
-
+ /* load attributes in generic way
/* save all attributes in linked list */
LY_ARRAY_FOR(attrs, struct yin_arg_record, iter) {
new = calloc(1, sizeof(*last));
@@ -3411,7 +3397,6 @@
}
}
-
/* parse content of element if any */
if (ctx->xml_ctx.status == LYXML_ELEM_CONTENT) {
ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
@@ -3423,7 +3408,7 @@
/* end of element reached */
break;
}
- LY_CHECK_RET(yin_parse_element_generic(ctx, temp_name, temp_name_len, temp_prefix, temp_prefix_len, data, &new));
+ LY_CHECK_RET(yin_parse_element_generic(ctx, temp_name, temp_name_len, temp_prefix, temp_prefix_len, (*element)->kw, data, &new));
if (!(*element)->child) {
/* save first */
(*element)->child = new;
diff --git a/src/parser_yin.h b/src/parser_yin.h
index c4c02b9..2e6bc93 100644
--- a/src/parser_yin.h
+++ b/src/parser_yin.h
@@ -252,15 +252,16 @@
* @param[in,out] ctx Yin parser context for logging and to store current state.
* @param[in] name Name of element.
* @param[in] name_len Length of elements Name.
- * @param[in] name prefix of element.
- * @param[in] name_len Length of elements prefix.
+ * @param[in] prefix Prefix of element.
+ * @param[in] prefix_len Length of elements prefix.
+ * @param[in] parent Identification of parent element.
* @param[in,out] data Data to read from, always moved to currently handled character.
* @param[out] element Where the element structure should be stored.
*
* @return LY_ERR values.
*/
-LY_ERR yin_parse_element_generic(struct yin_parser_ctx *ctx, const char *name, size_t name_len, const char *prefix, size_t prefix_len, const char **data,
- struct lysp_stmt **element);
+LY_ERR yin_parse_element_generic(struct yin_parser_ctx *ctx, const char *name, size_t name_len, const char *prefix, size_t prefix_len, enum ly_stmt parent,
+ const char **data, struct lysp_stmt **element);
/**
* @brief Parse module element.
diff --git a/tests/src/test_parser_yin.c b/tests/src/test_parser_yin.c
index afbb73d..63d0ef8 100644
--- a/tests/src/test_parser_yin.c
+++ b/tests/src/test_parser_yin.c
@@ -373,7 +373,7 @@
const char *data = "<myext:elem attr=\"value\" xmlns:myext=\"urn:example:extensions\">text_value</myext:elem>";
lyxml_get_element(&st->yin_ctx->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
- ret = yin_parse_element_generic(st->yin_ctx, name, name_len, prefix, prefix_len, &data, &exts.child);
+ ret = yin_parse_element_generic(st->yin_ctx, name, name_len, prefix, prefix_len, LY_STMT_EXTENSION_INSTANCE, &data, &exts.child);
assert_int_equal(ret, LY_SUCCESS);
assert_int_equal(st->yin_ctx->xml_ctx.status, LYXML_END);
assert_string_equal(exts.child->stmt, "myext:elem");
@@ -386,7 +386,7 @@
data = "<myext:elem xmlns:myext=\"urn:example:extensions\"></myext:elem>";
lyxml_get_element(&st->yin_ctx->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
- ret = yin_parse_element_generic(st->yin_ctx, name, name_len, prefix, prefix_len, &data, &exts.child);
+ ret = yin_parse_element_generic(st->yin_ctx, name, name_len, prefix, prefix_len, LY_STMT_EXTENSION_INSTANCE, &data, &exts.child);
assert_int_equal(ret, LY_SUCCESS);
assert_string_equal(exts.child->stmt, "myext:elem");
assert_null(exts.child->child);
@@ -4365,7 +4365,7 @@
cmocka_unit_test_setup_teardown(test_yin_match_keyword, setup_f, teardown_f),
cmocka_unit_test_setup_teardown(test_yin_parse_element_generic, setup_f, teardown_f),
cmocka_unit_test_setup_teardown(test_yin_parse_extension_instance, setup_f, teardown_f),
- // cmocka_unit_test_setup_teardown(test_yin_parse_content, setup_f, teardown_f),
+ cmocka_unit_test_setup_teardown(test_yin_parse_content, setup_f, teardown_f),
cmocka_unit_test_setup_teardown(test_validate_value, setup_f, teardown_f),
cmocka_unit_test(test_yin_match_argument_name),