yin parser CHANGE add support for revision element
diff --git a/src/parser_yin.c b/src/parser_yin.c
index 7425416..bc2d861 100644
--- a/src/parser_yin.c
+++ b/src/parser_yin.c
@@ -1196,7 +1196,7 @@
                                             {YANG_UNITS, &llist->units, YIN_SUBELEM_UNIQUE},
                                             {YANG_WHEN, &llist->when, YIN_SUBELEM_UNIQUE},
                                             {YANG_CUSTOM, NULL, 0},
-                                         };
+                                        };
     LY_CHECK_RET(yin_parse_content(ctx, subelems, 14, data, YANG_LEAF_LIST, NULL, &llist->exts));
 
     /* invalid combination of subelements */
@@ -1243,7 +1243,7 @@
                                             {YANG_TYPE, &tpdf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
                                             {YANG_UNITS, &tpdf->units, YIN_SUBELEM_UNIQUE},
                                             {YANG_CUSTOM, NULL, 0},
-                                         };
+                                        };
     LY_CHECK_RET(yin_parse_content(ctx, subelems, 7, data, YANG_TYPEDEF, NULL, &tpdf->exts));
 
     /* store data for collision check */
@@ -1290,7 +1290,7 @@
                                             {YANG_PRESENCE, &rf->presence, YIN_SUBELEM_UNIQUE},
                                             {YANG_REFERENCE, &rf->ref, YIN_SUBELEM_UNIQUE},
                                             {YANG_CUSTOM, NULL, 0},
-                                         };
+                                        };
     return yin_parse_content(ctx, subelems, 11, data, YANG_REFINE, NULL, &rf->exts);
 }
 
@@ -1339,7 +1339,7 @@
                                             {YANG_STATUS, &uses->flags, YIN_SUBELEM_UNIQUE},
                                             {YANG_WHEN, &uses->when, YIN_SUBELEM_UNIQUE},
                                             {YANG_CUSTOM, NULL, 0},
-                                         };
+                                        };
     LY_CHECK_RET(yin_parse_content(ctx, subelems, 8, data, YANG_USES, NULL, &uses->exts));
     LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, uses->augments, NULL, NULL));
 
@@ -1347,6 +1347,45 @@
 }
 
 /**
+ * @brief Parse revision element.
+ *
+ * @param[in,out] ctx YIN parser context for logging and to store current state.
+ * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
+ * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] revs Parsed revisions to add to.
+ *
+ * @return LY_ERR values.
+ */
+static LY_ERR
+yin_parse_revision(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
+                   struct lysp_revision **revs)
+{
+    struct lysp_revision *rev;
+    const char *temp_date = NULL;
+
+    /* allocate new reivison */
+    LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *revs, rev, LY_EMEM);
+
+    /* parse argument */
+    LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_DATE, &temp_date, Y_STR_ARG, YANG_REVISION));
+    /* check value */
+    if (lysp_check_date((struct lys_parser_ctx *)ctx, temp_date, strlen(temp_date), "revision")) {
+        FREE_STRING(ctx->xml_ctx.ctx, temp_date);
+        return LY_EVALID;
+    }
+    strcpy(rev->date, temp_date);
+    FREE_STRING(ctx->xml_ctx.ctx, temp_date);
+
+    /* parse content */
+    struct yin_subelement subelems[3] = {
+                                            {YANG_DESCRIPTION, &rev->dsc, YIN_SUBELEM_UNIQUE},
+                                            {YANG_REFERENCE, &rev->ref, YIN_SUBELEM_UNIQUE},
+                                            {YANG_CUSTOM, NULL, 0},
+                                        };
+    return yin_parse_content(ctx, subelems, 3, data, YANG_REVISION, NULL, &rev->exts);
+}
+
+/**
  * @brief Map keyword type to substatement info.
  *
  * @param[in] kw Keyword type.
@@ -1680,6 +1719,7 @@
                     ret = yin_pasrse_reqinstance(ctx, attrs, data, (struct lysp_type *)subelem->dest);
                     break;
                 case YANG_REVISION:
+                    ret = yin_parse_revision(ctx, attrs, data, (struct lysp_revision **)subelem->dest);
                     break;
                 case YANG_REVISION_DATE:
                     ret = yin_parse_revision_date(ctx, attrs, data, (char *)subelem->dest, exts);
diff --git a/src/tree_schema_free.c b/src/tree_schema_free.c
index 8895385..8ad404f 100644
--- a/src/tree_schema_free.c
+++ b/src/tree_schema_free.c
@@ -76,7 +76,7 @@
     FREE_ARRAY(ctx, include->exts, lysp_ext_instance_free);
 }
 
-static void
+void
 lysp_revision_free(struct ly_ctx *ctx, struct lysp_revision *rev)
 {
     FREE_STRING(ctx, rev->dsc);
diff --git a/tests/src/test_parser_yin.c b/tests/src/test_parser_yin.c
index 0e3231c..03d145c 100644
--- a/tests/src/test_parser_yin.c
+++ b/tests/src/test_parser_yin.c
@@ -35,6 +35,7 @@
 void lysp_node_free(struct ly_ctx *ctx, struct lysp_node *node);
 void lysp_tpdf_free(struct ly_ctx *ctx, struct lysp_tpdf *tpdf);
 void lysp_refine_free(struct ly_ctx *ctx, struct lysp_refine *ref);
+void lysp_revision_free(struct ly_ctx *ctx, struct lysp_revision *rev);
 
 struct state {
     struct ly_ctx *ctx;
@@ -2332,6 +2333,44 @@
     st->finished_correctly = true;
 }
 
+static void
+test_revision_elem(void **state)
+{
+    struct state *st = *state;
+    const char *data;
+    struct lysp_revision *revs = NULL;
+
+    /* max subelems */
+    data = ELEMENT_WRAPPER_START
+                "<revision date=\"2018-12-25\">"
+                    "<description><text>desc</text></description>"
+                    "<reference><text>ref</text></reference>"
+                "</revision>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, &data, &revs, NULL, NULL, true), LY_SUCCESS);
+    assert_string_equal(revs->date, "2018-12-25");
+    assert_string_equal(revs->dsc, "desc");
+    assert_string_equal(revs->ref, "ref");
+    FREE_ARRAY(st->ctx, revs, lysp_revision_free);
+    revs = NULL;
+
+    /* min subelems */
+    data = ELEMENT_WRAPPER_START "<revision date=\"2005-05-05\" />" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, &data, &revs, NULL, NULL, true), LY_SUCCESS);
+    assert_string_equal(revs->date, "2005-05-05");
+    FREE_ARRAY(st->ctx, revs, lysp_revision_free);
+    revs = NULL;
+
+    /* invalid value */
+    data = ELEMENT_WRAPPER_START "<revision date=\"05-05-2005\" />" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, &data, &revs, NULL, NULL, false), LY_EVALID);
+    logbuf_assert("Invalid value \"05-05-2005\" of \"revision\". Line number 1.");
+    FREE_ARRAY(st->ctx, revs, lysp_revision_free);
+    revs = NULL;
+
+    st->finished_correctly = true;
+}
+
 int
 main(void)
 {
@@ -2388,6 +2427,7 @@
         cmocka_unit_test_setup_teardown(test_typedef_elem, setup_element_test, teardown_element_test),
         cmocka_unit_test_setup_teardown(test_refine_elem, setup_element_test, teardown_element_test),
         cmocka_unit_test_setup_teardown(test_uses_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_revision_elem, setup_element_test, teardown_element_test),
     };
 
     return cmocka_run_group_tests(tests, setup_ly_ctx, destroy_ly_ctx);