yin parser CHANGE add functions for checking of subelement constraints
diff --git a/src/common.c b/src/common.c
index 76f3b84..20fcb0f 100644
--- a/src/common.c
+++ b/src/common.c
@@ -100,6 +100,8 @@
     [YANG_SEMICOLON] = ";",
     [YANG_LEFT_BRACE] = "{",
     [YANG_RIGHT_BRACE] = "}",
+    [YIN_TEXT] = "text",
+    [YIN_VALUE] = "value",
 };
 
 const char *const lyext_substmt_list[] = {
diff --git a/src/parser_yin.c b/src/parser_yin.c
index cf5d05c..a805f51 100644
--- a/src/parser_yin.c
+++ b/src/parser_yin.c
@@ -220,14 +220,14 @@
                     LY_CHECK_RET(!(*arg_val), LY_EMEM);
                 }
             } else {
-                LOGERR(xml_ctx->ctx, LYVE_SYNTAX_YIN, "Unexpected attribute \"%.*s\".", iter->name_len, iter->name);
+                LOGVAL_PARSER(xml_ctx, LYVE_SYNTAX_YIN, "Unexpected attribute \"%.*s\" of %s element.", iter->name_len, iter->name, ly_stmt2str(current_element));
                 return LY_EVALID;
             }
         }
     }
 
     if (flags & YIN_ARG_MANDATORY && !found) {
-        LOGVAL_PARSER(xml_ctx, LYVE_SYNTAX_YIN, "Missing mandatory attribute \"%s\" of %s element", yin_attr2str(arg_type), ly_stmt2str(current_element));
+        LOGVAL_PARSER(xml_ctx, LYVE_SYNTAX_YIN, "Missing mandatory attribute \"%s\" of %s element.", yin_attr2str(arg_type), ly_stmt2str(current_element));
         return LY_EVALID;
     }
 
@@ -255,6 +255,35 @@
     return NULL;
 }
 
+LY_ERR
+yin_check_subelem_mandatory_constraint(struct lyxml_context *xml_ctx, struct yin_subelement *subelem_info,
+                                       size_t subelem_info_size, enum yang_keyword current_element)
+{
+    for (size_t i = 0; i < subelem_info_size; ++i) {
+        /* if there is element that is mandatory and isn't parsed log error and rturn LY_EVALID */
+        if (subelem_info[i].flags & YIN_SUBELEM_MANDATORY && !(subelem_info[i].flags & YIN_SUBELEM_PARSED)) {
+            LOGVAL_PARSER(xml_ctx, LYVE_SYNTAX_YIN, "Missing mandatory subelement %s of %s element", ly_stmt2str(subelem_info[i].type), ly_stmt2str(current_element));
+            return LY_EVALID;
+        }
+    }
+
+    return LY_SUCCESS;
+}
+
+LY_ERR
+yin_check_subelem_first_constraint(struct lyxml_context *xml_ctx, struct yin_subelement *subelem_info,
+                                   size_t subelem_info_size, enum yang_keyword current_element, struct yin_subelement *exp_first)
+{
+    for (size_t i = 0; i < subelem_info_size; ++i) {
+        if (subelem_info[i].flags & YIN_SUBELEM_PARSED) {
+            LOGVAL_PARSER(xml_ctx, LYVE_SYNTAX_YIN, "Subelement %s of %s element must be defined as first subelement.", exp_first->type, current_element);
+            return LY_EVALID;
+        }
+    }
+
+    return LY_SUCCESS;
+}
+
 /**
  * @brief Generic function for content parsing
  *
@@ -305,7 +334,16 @@
                 }
 
                 /* TODO macro to check order */
-                /* TODO flag check */
+                /* if element is unique and already defined log error */
+                if (subelem_info_rec->flags & YIN_SUBELEM_UNIQUE & YIN_SUBELEM_PARSED) {
+                    LOGVAL_PARSER(xml_ctx, LYVE_SYNTAX_YIN, "Redefinition of %s element in %s element.", kw, current_element);
+                    return LY_EVALID;
+                }
+                if (subelem_info_rec->flags & YIN_SUBELEM_FIRST) {
+                    yin_check_subelem_first_constraint(xml_ctx, subelem_info, subelem_info_size, current_element, subelem_info_rec);
+                }
+                subelem_info_rec->flags |= YIN_SUBELEM_PARSED;
+
                 switch (kw) {
                 case YANG_CUSTOM:
                     /* TODO write function to calculate index instead of hardcoded 0 */
@@ -462,14 +500,16 @@
                 case YIN_VALUE:
                     break;
                 default:
-                    /* TODO special cases */
-                    break;
+                    LOGINT(xml_ctx->ctx);
+                    return LY_EINT;
                 }
                 LY_CHECK_GOTO(ret, cleanup);
                 FREE_ARRAY(xml_ctx, subelem_attrs, free_arg_rec);
                 subelem_attrs = NULL;
                 subelem_info_rec = NULL;
             }
+            LY_CHECK_RET(yin_check_subelem_mandatory_constraint(xml_ctx, subelem_info, subelem_info_size, current_element));
+
         } else {
             /* elements with text or none content */
             /* save text content, if text_content isn't set, it's just ignored */
@@ -498,8 +538,6 @@
     return ret;
 }
 
-#define YIN_ARG_REQUIRED 0x01
-
 LY_ERR
 yin_parse_simple_element(struct lyxml_context *xml_ctx, struct yin_arg_record *attrs, const char **data, enum yang_keyword kw,
                          const char **value, enum YIN_ARGUMENT arg_type, uint8_t argument_flags, struct lysp_ext_instance **exts)
@@ -604,7 +642,8 @@
                        const char **value, struct lysp_ext_instance **exts)
 {
     assert(elem_type == YANG_ORGANIZATION || elem_type == YANG_CONTACT || elem_type == YANG_DESCRIPTION || elem_type == YANG_REFERENCE);
-    struct yin_subelement subelems[2] = {{YIN_TEXT, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
+
+    struct yin_subelement subelems[2] = {{YIN_TEXT, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST},
                                          {YANG_CUSTOM, NULL, 0}};
 
     return yin_parse_content(xml_ctx, subelems, 2, data, elem_type, NULL, exts);
diff --git a/src/parser_yin.h b/src/parser_yin.h
index dd8a3fc..894570d 100644
--- a/src/parser_yin.h
+++ b/src/parser_yin.h
@@ -60,7 +60,9 @@
 /* flags to encode cardinality of subelement */
 #define YIN_SUBELEM_MANDATORY   0x01    /**< is set when subelement is mandatory */
 #define YIN_SUBELEM_UNIQUE      0x02    /**< is set when subelement is unique */
-#define YIN_SUBELEM_PARSED      0x04    /**< is set during parsing when given subelement is encountered for the first
+#define YIN_SUBELEM_FIRST       0x08    /**< is set when subelement is actually yang argument mapped to yin element */
+
+#define YIN_SUBELEM_PARSED      0x80    /**< is set during parsing when given subelement is encountered for the first
                                              time to simply check validity of given constraints */
 
 #define YIN_ARG_MANDATORY       0x01    /**< is set when attribute is mandatory */
diff --git a/tests/src/test_parser_yin.c b/tests/src/test_parser_yin.c
index 0f5d1a6..50f2fa8 100644
--- a/tests/src/test_parser_yin.c
+++ b/tests/src/test_parser_yin.c
@@ -188,7 +188,7 @@
                             </module>",
                            st->mod);
     assert_int_equal(ret, LY_EVALID);
-    logbuf_assert("Missing mandatory attribute \"name\" of module element Line number 1.");
+    logbuf_assert("Missing mandatory attribute \"name\" of module element. Line number 1.");
 
     st = reset_state(state);
     ret = yin_parse_module(st->ctx,
@@ -314,6 +314,8 @@
 
     ret = yin_parse_module(st->ctx,"<module xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\
                                         name=\"example-foo\">\
+                                        <prefix value=\"foo\">ignored</prefix>\
+                                        <namespace uri=\"urn:example:foo\" xmlns:myext=\"urn:example:extensions\"/>\
                                         <organization xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"><text>organization...</text></organization>\
                                         <contact><text>contact...</text></contact>\
                                         <description><text>description...</text></description>\