yin parser CHANGE parse known extension subelements correctly finished
diff --git a/src/common.h b/src/common.h
index 342e144..744b1c5 100644
--- a/src/common.h
+++ b/src/common.h
@@ -546,7 +546,7 @@
         if (ARRAY){free((uint32_t*)(ARRAY) - 1);}
 
 /**
- * @brief insert item into linked list.
+ * @brief Insert item into linked list.
  *
  * @param[in,out] LIST Linked list to add to.
  * @param[in] NEW_ITEM New item, that will be appended to the list, must be already allocated.
@@ -564,7 +564,7 @@
     }
 
 /**
- * @brief allocate and insert new item into linked list.
+ * @brief Allocate and insert new item into linked list, return in case of error.
  *
  * @param[in] CTX used for logging.
  * @param[in,out] LIST Linked list to add to.
@@ -577,7 +577,7 @@
     LY_LIST_INSERT(LIST, NEW_ITEM, LINKER)
 
 /**
- * @brief allocate and insert new item into linked list.
+ * @brief Allocate and insert new item into linked list, goto specified label in case of error.
  *
  * @param[in] CTX used for logging.
  * @param[in,out] LIST Linked list to add to.
diff --git a/src/parser_yin.c b/src/parser_yin.c
index 3576471..914f6f9 100644
--- a/src/parser_yin.c
+++ b/src/parser_yin.c
@@ -3210,20 +3210,28 @@
     return LY_SUCCESS;
 }
 
-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, 
-                          enum ly_stmt parent, struct lysp_stmt **args)
+/**
+ * @brief Parse argument of extension subelement that is classic yang keyword and not another instance of extension.
+ *
+ * @param[in,out] ctx Yin parser context for logging and to store current state.
+ * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of extension instance.
+ * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in] elem_type Type of element that is currently being parsed.
+ * @param[out] arg Value to write to.
+ *
+ * @return LY_ERR values.
+ */
+static 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,
+                          const char **arg)
 {
     LY_ERR ret = LY_SUCCESS;
-    struct lysp_stmt *arg;
     char *out = NULL;
     const char *name, *prefix;
     size_t out_len, name_len, prefix_len;
     int dynamic;
     enum ly_stmt child;
 
-    LY_LIST_NEW_RET(ctx->xml_ctx.ctx, args, arg, next);
-
     switch (elem_type) {
     case LY_STMT_ACTION:
     case LY_STMT_ANYDATA:
@@ -3251,12 +3259,12 @@
     case LY_STMT_TYPEDEF:
     case LY_STMT_UNITS:
     case LY_STMT_USES:
-        LY_CHECK_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, Y_MAYBE_STR_ARG, elem_type));
         break;
     case LY_STMT_AUGMENT:
     case LY_STMT_DEVIATION:
     case LY_STMT_REFINE:
-        LY_CHECK_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, Y_MAYBE_STR_ARG, elem_type));
         break;
     case LY_STMT_CONFIG:
     case LY_STMT_DEFAULT:
@@ -3281,30 +3289,30 @@
     case LY_STMT_VALUE:
     case LY_STMT_YANG_VERSION:
     case LY_STMT_YIN_ELEMENT:
-        LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &arg->arg, Y_MAYBE_STR_ARG, elem_type));
+        LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, arg, Y_MAYBE_STR_ARG, elem_type));
         break;
     case LY_STMT_IMPORT:
     case LY_STMT_INCLUDE:
     case LY_STMT_BELONGS_TO:
-        LY_CHECK_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, Y_MAYBE_STR_ARG, elem_type));
         break;
     case LY_STMT_INPUT:
     case LY_STMT_OUTPUT:
-        LY_CHECK_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, Y_MAYBE_STR_ARG, elem_type));
         break;
     case LY_STMT_MUST:
     case LY_STMT_WHEN:
-        LY_CHECK_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, Y_MAYBE_STR_ARG, elem_type));
         break;
     case LY_STMT_NAMESPACE:
-        LY_CHECK_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, Y_MAYBE_STR_ARG, elem_type));
         break;
     case LY_STMT_REVISION:
     case LY_STMT_REVISION_DATE:
-        LY_CHECK_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, Y_MAYBE_STR_ARG, elem_type));
         break;
     case LY_STMT_UNIQUE:
-        LY_CHECK_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, Y_MAYBE_STR_ARG, elem_type));
         break;
     /* argument is mapped to yin element */
     case LY_STMT_CONTACT:
@@ -3312,22 +3320,29 @@
     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));
+        /* there shouldn't be any attribute, argument is supposed to be first subelement */
+        LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NONE, 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_ERR_RET(ret != LY_EINVAL, LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_FIRT_SUBELEM,
+                                                         elem_type == LY_STMT_ERROR_MESSAGE ? "value" : "text", ly_stmt2str(elem_type)),
+                        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);
+        if ((elem_type == LY_STMT_ERROR_MESSAGE && child == LY_STMT_ARG_VALUE) ||
+            (elem_type != LY_STMT_ERROR_MESSAGE && child == LY_STMT_ARG_TEXT)) {
+            LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, name_len, name, ly_stmt2str(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 */
+        INSERT_STRING(ctx->xml_ctx.ctx, *arg, dynamic, out, out_len);
+        LY_CHECK_RET(!*arg, LY_EMEM);
+        /* load closing tag of subelement */
         LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
+        /* if only subelement was parsed as argument, load also closing tag */
+        if (ctx->xml_ctx.status == LYXML_ELEMENT) {
+            LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
+        }
         break;
     default:
         LOGINT(ctx->xml_ctx.ctx);
@@ -3338,7 +3353,7 @@
 }
 
 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, 
+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;
@@ -3359,23 +3374,23 @@
 
     ret = yin_load_attributes(ctx, data, &attrs);
     LY_CHECK_GOTO(ret, cleanup);
-    (*element)->kw = yin_match_keyword(ctx, name, name_len, prefix, prefix_len, LY_STMT_EXTENSION_INSTANCE);
+    (*element)->kw = yin_match_keyword(ctx, name, name_len, prefix, prefix_len, parent);
 
     last = (*element)->child;
     if ((*element)->kw == LY_STMT_NONE) {
         /* unrecognized element */
-        /* TODO set parrent correctly */
-        LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, name_len, name, ly_stmt2str(LY_STMT_EXTENSION_INSTANCE));
-        return LY_EVALID;
+        LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, name_len, name, ly_stmt2str(parent));
+        ret = LY_EVALID;
+        goto cleanup;
     } 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, parent, &(*element)->child));
+        ret = yin_parse_arg_inext_known(ctx, attrs, data, (*element)->kw, &(*element)->arg);
+        LY_CHECK_GOTO(ret, cleanup);
     } else {
-        /* load attributes in generic way
-        /* save all attributes in linked list */
+        /* 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));
-            LY_CHECK_ERR_RET(!new, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
+            LY_CHECK_ERR_GOTO(!new, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, cleanup);
             if (!(*element)->child) {
                 /* save first */
                 (*element)->child = new;
@@ -3390,7 +3405,7 @@
             /* attributes with prefix are ignored */
             if (!iter->prefix) {
                 INSERT_STRING(ctx->xml_ctx.ctx, last->arg, iter->dynamic_content, iter->content, iter->content_len);
-                LY_CHECK_RET(!last->arg, LY_EMEM);
+                LY_CHECK_ERR_GOTO(!last->arg, ret = LY_EMEM, cleanup);
                 /* string is no longer supposed to be freed when the array is freed */
                 iter->dynamic_content = 0;
             }
@@ -3403,12 +3418,14 @@
         if (ret == LY_EINVAL) {
             while (ctx->xml_ctx.status == LYXML_ELEMENT) {
                 /* parse subelements */
-                LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &temp_prefix, &temp_prefix_len, &temp_name, &temp_name_len));
+                ret = lyxml_get_element(&ctx->xml_ctx, data, &temp_prefix, &temp_prefix_len, &temp_name, &temp_name_len);
+                LY_CHECK_GOTO(ret , cleanup);
                 if (!temp_name) {
                     /* end of element reached */
                     break;
                 }
-                LY_CHECK_RET(yin_parse_element_generic(ctx, temp_name, temp_name_len, temp_prefix, temp_prefix_len, (*element)->kw, data, &new));
+                ret = yin_parse_element_generic(ctx, temp_name, temp_name_len, temp_prefix, temp_prefix_len, (*element)->kw, data, &new);
+                LY_CHECK_GOTO(ret, cleanup);
                 if (!(*element)->child) {
                     /* save first */
                     (*element)->child = new;
@@ -3419,15 +3436,16 @@
             }
         ret = LY_SUCCESS;
         } else {
-            LY_CHECK_RET(ret);
+            LY_CHECK_GOTO(ret, cleanup);
             /* save element content */
             if (out_len != 0) {
                 INSERT_STRING(ctx->xml_ctx.ctx, (*element)->arg, dynamic, out, out_len);
-                LY_CHECK_RET(!(*element)->arg, LY_EMEM);
+                LY_CHECK_ERR_GOTO(!(*element)->arg, ret = LY_EMEM, cleanup);
             }
 
             /* read closing tag */
-            LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &temp_prefix, &temp_prefix_len, &temp_name, &temp_name_len));
+            ret = lyxml_get_element(&ctx->xml_ctx, data, &temp_prefix, &temp_prefix_len, &temp_name, &temp_name_len);
+            LY_CHECK_GOTO(ret, cleanup);
         }
     }
 
diff --git a/src/parser_yin.h b/src/parser_yin.h
index 2e6bc93..0e5d56c 100644
--- a/src/parser_yin.h
+++ b/src/parser_yin.h
@@ -215,7 +215,7 @@
  * @return yang_keyword values.
  */
 enum ly_stmt yin_match_keyword(struct yin_parser_ctx *ctx, const char *name, size_t name_len,
-                                    const char *prefix, size_t prefix_len, enum ly_stmt parrent);
+                               const char *prefix, size_t prefix_len, enum ly_stmt parrent);
 
 /**
  * @brief Load all attributes of element into ([sized array](@ref sizedarrays)). Caller is suposed to free the array.
@@ -260,7 +260,7 @@
  *
  * @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, enum ly_stmt parent, 
+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);
 
 /**