schema parsers CHANGE make lys_parse_mem functions compatible with yin_parser_ctx
diff --git a/src/parser_yang.c b/src/parser_yang.c
index 31a740c..aa58756 100644
--- a/src/parser_yang.c
+++ b/src/parser_yang.c
@@ -4490,7 +4490,7 @@
 }
 
 LY_ERR
-yang_parse_submodule(struct lys_parser_ctx *context, const char *data, struct lysp_submodule **submod)
+yang_parse_submodule(struct lys_parser_ctx **context, struct ly_ctx *ly_ctx, struct lys_parser_ctx *main_ctx, const char *data, struct lysp_submodule **submod)
 {
     LY_ERR ret = LY_SUCCESS;
     char *word;
@@ -4498,27 +4498,37 @@
     enum yang_keyword kw;
     struct lysp_submodule *mod_p = NULL;
 
+    /* create context */
+    *context = calloc(1, sizeof **context);
+    LY_CHECK_ERR_RET(!(*context), LOGMEM(ly_ctx), LY_EMEM);
+    (*context)->ctx = ly_ctx;
+    (*context)->line = 1;
+
+    /* map the typedefs and groupings list from main context to the submodule's context */
+    memcpy(&(*context)->tpdfs_nodes, &main_ctx->tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
+    memcpy(&(*context)->grps_nodes, &main_ctx->grps_nodes, sizeof main_ctx->grps_nodes);
+
     /* "module"/"submodule" */
-    ret = get_keyword(context, &data, &kw, &word, &word_len);
+    ret = get_keyword(*context, &data, &kw, &word, &word_len);
     LY_CHECK_GOTO(ret, cleanup);
 
     if (kw == YANG_MODULE) {
-        LOGERR(context->ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
+        LOGERR((*context)->ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
         ret = LY_EINVAL;
         goto cleanup;
     } else if (kw != YANG_SUBMODULE) {
-        LOGVAL_PARSER(context, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
+        LOGVAL_PARSER(*context, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
                ly_stmt2str(kw));
         ret = LY_EVALID;
         goto cleanup;
     }
 
     mod_p = calloc(1, sizeof *mod_p);
-    LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(context->ctx), cleanup);
+    LY_CHECK_ERR_GOTO(!mod_p, LOGMEM((*context)->ctx), cleanup);
     mod_p->parsing = 1;
 
     /* substatements */
-    ret = parse_submodule(context, &data, mod_p);
+    ret = parse_submodule(*context, &data, mod_p);
     LY_CHECK_GOTO(ret, cleanup);
 
     /* read some trailing spaces or new lines */
@@ -4526,7 +4536,7 @@
         data++;
     }
     if (*data) {
-        LOGVAL_PARSER(context, LYVE_SYNTAX, "Trailing garbage \"%.*s%s\" after submodule, expected end-of-input.",
+        LOGVAL_PARSER(*context, LYVE_SYNTAX, "Trailing garbage \"%.*s%s\" after submodule, expected end-of-input.",
                     15, data, strlen(data) > 15 ? "..." : "");
         ret = LY_EVALID;
         goto cleanup;
@@ -4537,14 +4547,16 @@
 
 cleanup:
     if (ret) {
-        lysp_submodule_free(context->ctx, mod_p);
+        lysp_submodule_free((*context)->ctx, mod_p);
+        lys_parser_ctx_free(*context);
+        *context = NULL;
     }
 
     return ret;
 }
 
 LY_ERR
-yang_parse_module(struct lys_parser_ctx *context, const char *data, struct lys_module *mod)
+yang_parse_module(struct lys_parser_ctx **context, const char *data, struct lys_module *mod)
 {
     LY_ERR ret = LY_SUCCESS;
     char *word;
@@ -4552,28 +4564,34 @@
     enum yang_keyword kw;
     struct lysp_module *mod_p = NULL;
 
+    /* create context */
+    *context = calloc(1, sizeof **context);
+    LY_CHECK_ERR_RET(!(*context), LOGMEM(mod->ctx), LY_EMEM);
+    (*context)->ctx = mod->ctx;
+    (*context)->line = 1;
+
     /* "module"/"submodule" */
-    ret = get_keyword(context, &data, &kw, &word, &word_len);
+    ret = get_keyword(*context, &data, &kw, &word, &word_len);
     LY_CHECK_GOTO(ret, cleanup);
 
     if (kw == YANG_SUBMODULE) {
-        LOGERR(context->ctx, LY_EDENIED, "Input data contains submodule which cannot be parsed directly without its main module.");
+        LOGERR((*context)->ctx, LY_EDENIED, "Input data contains submodule which cannot be parsed directly without its main module.");
         ret = LY_EINVAL;
         goto cleanup;
     } else if (kw != YANG_MODULE) {
-        LOGVAL_PARSER(context, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
+        LOGVAL_PARSER((*context), LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
                ly_stmt2str(kw));
         ret = LY_EVALID;
         goto cleanup;
     }
 
     mod_p = calloc(1, sizeof *mod_p);
-    LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(context->ctx), cleanup);
+    LY_CHECK_ERR_GOTO(!mod_p, LOGMEM((*context)->ctx), cleanup);
     mod_p->mod = mod;
     mod_p->parsing = 1;
 
     /* substatements */
-    ret = parse_module(context, &data, mod_p);
+    ret = parse_module(*context, &data, mod_p);
     LY_CHECK_GOTO(ret, cleanup);
 
     /* read some trailing spaces or new lines */
@@ -4581,7 +4599,7 @@
         data++;
     }
     if (*data) {
-        LOGVAL_PARSER(context, LYVE_SYNTAX, "Trailing garbage \"%.*s%s\" after module, expected end-of-input.",
+        LOGVAL_PARSER(*context, LYVE_SYNTAX, "Trailing garbage \"%.*s%s\" after module, expected end-of-input.",
                     15, data, strlen(data) > 15 ? "..." : "");
         ret = LY_EVALID;
         goto cleanup;
@@ -4593,6 +4611,8 @@
 cleanup:
     if (ret) {
         lysp_module_free(mod_p);
+        lys_parser_ctx_free(*context);
+        *context = NULL;
     }
 
     return ret;
diff --git a/src/parser_yin.c b/src/parser_yin.c
index 7c278a0..ae037b3 100644
--- a/src/parser_yin.c
+++ b/src/parser_yin.c
@@ -3119,7 +3119,7 @@
 }
 
 LY_ERR
-yin_parse_submodule(struct yin_parser_ctx **yin_ctx, struct ly_ctx *ctx, const char *data, struct lysp_submodule **submod)
+yin_parse_submodule(struct yin_parser_ctx **yin_ctx, struct ly_ctx *ctx, struct lys_parser_ctx *main_ctx, const char *data, struct lysp_submodule **submod)
 {
     enum yang_keyword kw = YANG_NONE;
     LY_ERR ret = LY_SUCCESS;
@@ -3130,10 +3130,14 @@
 
     /* create context */
     *yin_ctx = calloc(1, sizeof **yin_ctx);
-    LY_CHECK_ERR_RET(!yin_ctx, LOGMEM(ctx), LY_EMEM);
+    LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(ctx), LY_EMEM);
     (*yin_ctx)->xml_ctx.ctx = ctx;
     (*yin_ctx)->xml_ctx.line = 1;
 
+    /* map the typedefs and groupings list from main context to the submodule's context */
+    memcpy(&(*yin_ctx)->tpdfs_nodes, &main_ctx->tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
+    memcpy(&(*yin_ctx)->grps_nodes, &main_ctx->grps_nodes, sizeof main_ctx->grps_nodes);
+
     /* check submodule */
     ret = lyxml_get_element(&(*yin_ctx)->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
     LY_CHECK_GOTO(ret, cleanup);
@@ -3178,6 +3182,8 @@
 cleanup:
     if (ret) {
         lysp_submodule_free(ctx, mod_p);
+        yin_parser_ctx_free(*yin_ctx);
+        *yin_ctx = NULL;
     }
 
     FREE_ARRAY(*yin_ctx, attrs, free_arg_rec);
@@ -3196,7 +3202,7 @@
 
     /* create context */
     *yin_ctx = calloc(1, sizeof **yin_ctx);
-    LY_CHECK_ERR_RET(!yin_ctx, LOGMEM(mod->ctx), LY_EMEM);
+    LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(mod->ctx), LY_EMEM);
     (*yin_ctx)->xml_ctx.ctx = mod->ctx;
     (*yin_ctx)->xml_ctx.line = 1;
 
@@ -3227,6 +3233,7 @@
     ret = yin_parse_mod(*yin_ctx, attrs, &data, mod_p);
     LY_CHECK_GOTO(ret, cleanup);
 
+    /* check trailing characters */
     if ((*yin_ctx)->xml_ctx.status == LYXML_ELEMENT) {
         ret = lyxml_get_element(&(*yin_ctx)->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
     }
@@ -3244,6 +3251,8 @@
 cleanup:
     if (ret != LY_SUCCESS) {
         lysp_module_free(mod_p);
+        yin_parser_ctx_free(*yin_ctx);
+        *yin_ctx = NULL;
     }
     FREE_ARRAY(*yin_ctx, attrs, free_arg_rec);
     return ret;
diff --git a/src/tree_schema.c b/src/tree_schema.c
index d828c67..25c4d64 100644
--- a/src/tree_schema.c
+++ b/src/tree_schema.c
@@ -595,28 +595,21 @@
 {
     LY_ERR ret = LY_EINVAL;
     struct lysp_submodule *submod = NULL, *latest_sp;
-    struct lys_parser_ctx context = {0};
+    struct lys_parser_ctx *context = NULL;
+    struct yin_parser_ctx *yin_context = NULL;
 
     LY_CHECK_ARG_RET(ctx, ctx, data, NULL);
 
-    context.ctx = ctx;
-    context.line = 1;
-
-    /* map the typedefs and groupings list from main context to the submodule's context */
-    memcpy(&context.tpdfs_nodes, &main_ctx->tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
-    memcpy(&context.grps_nodes, &main_ctx->grps_nodes, sizeof main_ctx->grps_nodes);
-
     switch (format) {
-    /* TODO not yet supported
     case LYS_IN_YIN:
-        mod = yin_read_module();
+        ret = yin_parse_submodule(&yin_context, ctx, main_ctx, data, &submod);
+        context = (struct lys_parser_ctx *)yin_context;
         break;
-    */
     case LYS_IN_YANG:
-        ret = yang_parse_submodule(&context, data, &submod);
+        ret = yang_parse_submodule(&context, ctx, main_ctx, data, &submod);
         break;
     default:
-        LOGERR(context.ctx, LY_EINVAL, "Invalid schema input format.");
+        LOGERR((*context).ctx, LY_EINVAL, "Invalid schema input format.");
         break;
     }
     LY_CHECK_RET(ret, NULL);
@@ -625,11 +618,11 @@
     lysp_sort_revisions(submod->revs);
 
     if (custom_check) {
-        LY_CHECK_GOTO(custom_check(context.ctx, NULL, submod, check_data), error);
+        LY_CHECK_GOTO(custom_check((*context).ctx, NULL, submod, check_data), error);
     }
 
     /* decide the latest revision */
-    latest_sp = ly_ctx_get_submodule(context.ctx, submod->belongsto, submod->name, NULL);
+    latest_sp = ly_ctx_get_submodule((*context).ctx, submod->belongsto, submod->name, NULL);
     if (latest_sp) {
         if (submod->revs) {
             if (!latest_sp->revs) {
@@ -648,12 +641,23 @@
     }
 
     /* remap possibly changed and reallocated typedefs and groupings list back to the main context */
-    memcpy(&main_ctx->tpdfs_nodes, &context.tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
-    memcpy(&main_ctx->grps_nodes, &context.grps_nodes, sizeof main_ctx->grps_nodes);
+    memcpy(&main_ctx->tpdfs_nodes, &(*context).tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
+    memcpy(&main_ctx->grps_nodes, &(*context).grps_nodes, sizeof main_ctx->grps_nodes);
 
+    if (format == LYS_IN_YANG) {
+        lys_parser_ctx_free(context);
+    } else {
+        yin_parser_ctx_free(yin_context);
+    }
     return submod;
+
 error:
     lysp_submodule_free(ctx, submod);
+    if (format == LYS_IN_YANG) {
+        lys_parser_ctx_free(context);
+    } else {
+        yin_parser_ctx_free(yin_context);
+    }
     return NULL;
 }
 
@@ -667,23 +671,20 @@
     struct lysp_include *inc;
     LY_ERR ret = LY_EINVAL;
     unsigned int u, i;
-    struct lys_parser_ctx context = {0};
+    struct lys_parser_ctx *context = NULL;
+    struct yin_parser_ctx *yin_context = NULL;
 
     LY_CHECK_ARG_RET(ctx, ctx, data, NULL);
 
-    context.ctx = ctx;
-    context.line = 1;
-
     mod = calloc(1, sizeof *mod);
     LY_CHECK_ERR_RET(!mod, LOGMEM(ctx), NULL);
     mod->ctx = ctx;
 
     switch (format) {
-    /* TODO not yet supported
     case LYS_IN_YIN:
-        mod = yin_read_module();
+        ret = yin_parse_module(&yin_context, data, mod);
+        context = (struct lys_parser_ctx *)yin_context;
         break;
-    */
     case LYS_IN_YANG:
         ret = yang_parse_module(&context, data, mod);
         break;
@@ -793,7 +794,7 @@
     }
     LY_ARRAY_FOR(mod->parsed->includes, u) {
         inc = &mod->parsed->includes[u];
-        if (!inc->submodule && lysp_load_submodule(&context, mod->parsed, inc)) {
+        if (!inc->submodule && lysp_load_submodule(context, mod->parsed, inc)) {
             goto error_ctx;
         }
         if (!mod->implemented) {
@@ -804,15 +805,26 @@
     mod->parsed->parsing = 0;
 
     /* check name collisions - typedefs and TODO groupings */
-    LY_CHECK_GOTO(lysp_check_typedefs(&context, mod->parsed), error_ctx);
+    LY_CHECK_GOTO(lysp_check_typedefs(context, mod->parsed), error_ctx);
 
+    if (format == LYS_IN_YANG) {
+        lys_parser_ctx_free(context);
+    } else {
+        yin_parser_ctx_free(yin_context);
+    }
     return mod;
 
 error_ctx:
     ly_set_rm(&ctx->list, mod, NULL);
 error:
     lys_module_free(mod, NULL);
-    ly_set_erase(&context.tpdfs_nodes, NULL);
+    ly_set_erase(&context->tpdfs_nodes, NULL);
+    if (format == LYS_IN_YANG) {
+        lys_parser_ctx_free(context);
+    } else {
+        yin_parser_ctx_free(yin_context);
+    }
+
     return NULL;
 }
 
diff --git a/src/tree_schema_free.c b/src/tree_schema_free.c
index 25fdf5f..edb2f10 100644
--- a/src/tree_schema_free.c
+++ b/src/tree_schema_free.c
@@ -867,8 +867,6 @@
 lys_parser_ctx_free(struct lys_parser_ctx *ctx)
 {
     if (ctx) {
-        ly_set_erase(&ctx->tpdfs_nodes, NULL);
-        ly_set_erase(&ctx->tpdfs_nodes, NULL);
         free(ctx);
     }
 }
@@ -878,8 +876,6 @@
 {
     if (ctx) {
         lyxml_context_clear(&ctx->xml_ctx);
-        ly_set_erase(&ctx->tpdfs_nodes, NULL);
-        ly_set_erase(&ctx->tpdfs_nodes, NULL);
         free(ctx);
     }
 }
diff --git a/src/tree_schema_internal.h b/src/tree_schema_internal.h
index b1da956..ffda7f5 100644
--- a/src/tree_schema_internal.h
+++ b/src/tree_schema_internal.h
@@ -787,12 +787,15 @@
 
 /**
  * @brief Parse submodule from YANG data.
- * @param[in] ctx Parser context.
+ * @param[in,out] ctx Parser context.
+ * @param[in] ly_ctx Context of YANG schemas.
+ * @param[in] main_ctx Parser context of main module.
  * @param[in] data Input data to be parsed.
  * @param[out] submod Pointer to the parsed submodule structure.
  * @return LY_ERR value - LY_SUCCESS, LY_EINVAL or LY_EVALID.
  */
-LY_ERR yang_parse_submodule(struct lys_parser_ctx *ctx, const char *data, struct lysp_submodule **submod);
+LY_ERR yang_parse_submodule(struct lys_parser_ctx **context, struct ly_ctx *ly_ctx, struct lys_parser_ctx *main_ctx,
+                            const char *data, struct lysp_submodule **submod);
 
 /**
  * @brief Parse module from YANG data.
@@ -802,7 +805,7 @@
  * module structure, will be filled in.
  * @return LY_ERR value - LY_SUCCESS, LY_EINVAL or LY_EVALID.
  */
-LY_ERR yang_parse_module(struct lys_parser_ctx *ctx, const char *data, struct lys_module *mod);
+LY_ERR yang_parse_module(struct lys_parser_ctx **context, const char *data, struct lys_module *mod);
 
 /**
  * @brief Parse module from YIN data.
@@ -821,14 +824,16 @@
  *
  * @param[in,out] yin_ctx Context created during parsing, is used to finalize lysp_model after it's completly parsed.
  * @param[in] ctx Libyang context.
- * @param[in,out] Data Input data to be parsed.
- * @param[in,out] mod Submodule structure where the parsed information, will be filled in.
+ * @param[in] main_ctx Parser context of main module.
+ * @param[in,out] data Input data to be parsed.
+ * @param[in,out] submod Submodule structure where the parsed information, will be filled in.
  *
  * @return LY_ERR values.
  */
-LY_ERR yin_parse_submodule(struct yin_parser_ctx **yin_ctx, struct ly_ctx *ctx,
+LY_ERR yin_parse_submodule(struct yin_parser_ctx **yin_ctx, struct ly_ctx *ctx, struct lys_parser_ctx *main_ctx,
                            const char *data, struct lysp_submodule **submod);
 
+
 /**
  * @brief Make the specific module implemented, use the provided value as flag.
  *
diff --git a/tests/src/test_context.c b/tests/src/test_context.c
index 78deffe..58f52d4 100644
--- a/tests/src/test_context.c
+++ b/tests/src/test_context.c
@@ -283,7 +283,7 @@
     assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
     assert_int_equal(ctx->module_set_id, ly_ctx_get_module_set_id(ctx));
 
-    assert_null(lys_parse_mem_module(ctx, "module x {namespace urn:x;prefix x;}", 3, 1, NULL, NULL));
+    assert_null(lys_parse_mem_module(ctx, "module x {namespace urn:x;prefix x;}", 4, 1, NULL, NULL));
     logbuf_assert("Invalid schema input format.");
 
     /* import callback */
diff --git a/tests/src/test_parser_yang.c b/tests/src/test_parser_yang.c
index 258cba7..e4adfd7 100644
--- a/tests/src/test_parser_yang.c
+++ b/tests/src/test_parser_yang.c
@@ -1047,20 +1047,23 @@
     assert_int_equal(2, mod->mod->version);
     mod = mod_renew(&ctx);
 
+    struct lys_parser_ctx *ctx_p = NULL;
     str = "module " SCHEMA_BEGINNING "} module q {namespace urn:q;prefixq;}";
     m = mod->mod;
     free(mod);
     m->parsed = NULL;
-    assert_int_equal(LY_EVALID, yang_parse_module(&ctx, str, m));
-    logbuf_assert("Trailing garbage \"module q {names...\" after module, expected end-of-input. Line number 3.");
+    assert_int_equal(LY_EVALID, yang_parse_module(&ctx_p, str, m));
+    logbuf_assert("Trailing garbage \"module q {names...\" after module, expected end-of-input. Line number 1.");
+    lys_parser_ctx_free(ctx_p);
     mod = mod_renew(&ctx);
 
     str = "prefix " SCHEMA_BEGINNING "}";
     m = mod->mod;
     free(mod);
     m->parsed = NULL;
-    assert_int_equal(LY_EVALID, yang_parse_module(&ctx, str, m));
-    logbuf_assert("Invalid keyword \"prefix\", expected \"module\" or \"submodule\". Line number 3.");
+    assert_int_equal(LY_EVALID, yang_parse_module(&ctx_p, str, m));
+    lys_parser_ctx_free(ctx_p);
+    logbuf_assert("Invalid keyword \"prefix\", expected \"module\" or \"submodule\". Line number 1.");
     mod = mod_renew(&ctx);
 
     str = "module " SCHEMA_BEGINNING "}";
@@ -1068,8 +1071,9 @@
     m = mod->mod;
     free(mod);
     m->parsed = NULL;
-    assert_int_equal(LY_EVALID, yang_parse_module(&ctx, str, m));
-    logbuf_assert("Invalid keyword \"position\" as a child of \"enum\". Line number 3.");
+    assert_int_equal(LY_EVALID, yang_parse_module(&ctx_p, str, m));
+    lys_parser_ctx_free(ctx_p);
+    logbuf_assert("Invalid keyword \"position\" as a child of \"enum\". Line number 1.");
     mod = mod_renew(&ctx);
 
     /* extensions */
@@ -1123,12 +1127,14 @@
     str = "submodule " SCHEMA_BEGINNING "} module q {namespace urn:q;prefixq;}";
     lysp_submodule_free(ctx.ctx, submod);
     submod = NULL;
-    assert_int_equal(LY_EVALID, yang_parse_submodule(&ctx, str, &submod));
-    logbuf_assert("Trailing garbage \"module q {names...\" after submodule, expected end-of-input. Line number 3.");
+    assert_int_equal(LY_EVALID, yang_parse_submodule(&ctx_p, ctx.ctx, &ctx, str, &submod));
+    lys_parser_ctx_free(ctx_p);
+    logbuf_assert("Trailing garbage \"module q {names...\" after submodule, expected end-of-input. Line number 1.");
 
     str = "prefix " SCHEMA_BEGINNING "}";
-    assert_int_equal(LY_EVALID, yang_parse_submodule(&ctx, str, &submod));
-    logbuf_assert("Invalid keyword \"prefix\", expected \"module\" or \"submodule\". Line number 3.");
+    assert_int_equal(LY_EVALID, yang_parse_submodule(&ctx_p, ctx.ctx, &ctx, str, &submod));
+    lys_parser_ctx_free(ctx_p);
+    logbuf_assert("Invalid keyword \"prefix\", expected \"module\" or \"submodule\". Line number 1.");
     submod = submod_renew(&ctx, submod);
 
 #undef TEST_GENERIC
diff --git a/tests/src/test_parser_yin.c b/tests/src/test_parser_yin.c
index 773dff3..2f06f45 100644
--- a/tests/src/test_parser_yin.c
+++ b/tests/src/test_parser_yin.c
@@ -3724,6 +3724,7 @@
     const char *data;
     struct yin_parser_ctx *yin_ctx = NULL;
     struct lysp_submodule *submod = NULL;
+    struct lys_parser_ctx main_ctx = {};
 
     data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
             "<submodule name=\"asub\""
@@ -3749,7 +3750,7 @@
                     "<container name=\"bar-sub2\"/>"
                 "</augment>"
             "</submodule>";
-    assert_int_equal(yin_parse_submodule(&yin_ctx, st->ctx, data, &submod), LY_SUCCESS);
+    assert_int_equal(yin_parse_submodule(&yin_ctx, st->ctx, &main_ctx, data, &submod), LY_SUCCESS);
     lysp_submodule_free(st->ctx, submod);
     yin_parser_ctx_free(yin_ctx);
     yin_ctx = NULL;
@@ -3762,7 +3763,7 @@
                     "<prefix value=\"a_pref\"/>"
                 "</belongs-to>"
             "</submodule>";
-    assert_int_equal(yin_parse_submodule(&yin_ctx, st->ctx, data, &submod), LY_SUCCESS);
+    assert_int_equal(yin_parse_submodule(&yin_ctx, st->ctx, &main_ctx, data, &submod), LY_SUCCESS);
     lysp_submodule_free(st->ctx, submod);
     yin_parser_ctx_free(yin_ctx);
     yin_ctx = NULL;
@@ -3771,7 +3772,7 @@
     data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
             "<module name=\"inval\" xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">"
             "</module>";
-    assert_int_equal(yin_parse_submodule(&yin_ctx, st->ctx, data, &submod), LY_EINVAL);
+    assert_int_equal(yin_parse_submodule(&yin_ctx, st->ctx, &main_ctx, data, &submod), LY_EINVAL);
     logbuf_assert("Input data contains module in situation when a submodule is expected.");
     lysp_submodule_free(st->ctx, submod);
     yin_parser_ctx_free(yin_ctx);
@@ -3791,7 +3792,7 @@
                     "<prefix value=\"a_pref\"/>"
                 "</belongs-to>"
             "</submodule>";
-    assert_int_equal(yin_parse_submodule(&yin_ctx, st->ctx, data, &submod), LY_EVALID);
+    assert_int_equal(yin_parse_submodule(&yin_ctx, st->ctx, &main_ctx, data, &submod), LY_EVALID);
     logbuf_assert("Trailing garbage \"<submodule name...\" after submodule, expected end-of-input. Line number 2.");
     lysp_submodule_free(st->ctx, submod);
     yin_parser_ctx_free(yin_ctx);
diff --git a/tests/src/test_tree_schema_compile.c b/tests/src/test_tree_schema_compile.c
index 08d847b..9063869 100644
--- a/tests/src/test_tree_schema_compile.c
+++ b/tests/src/test_tree_schema_compile.c
@@ -26,6 +26,7 @@
 #include "../../src/plugins_types.h"
 
 void lysc_feature_free(struct ly_ctx *ctx, struct lysc_feature *feat);
+void lys_parser_ctx_free(struct lys_parser_ctx *ctx);
 
 LY_ERR lys_path_token(const char **path, const char **prefix, size_t *prefix_len, const char **name, size_t *name_len,
                       int *parent_times, int *has_predicate);
@@ -95,20 +96,21 @@
 }
 
 static void
-reset_mod(struct ly_ctx *ctx, struct lys_module *module)
+reset_mod(struct lys_module *module)
 {
+    struct ly_ctx *ctx = module->ctx;
     lysc_module_free(module->compiled, NULL);
     lysp_module_free(module->parsed);
 
-    FREE_STRING(module->ctx, module->name);
-    FREE_STRING(module->ctx, module->ns);
-    FREE_STRING(module->ctx, module->prefix);
-    FREE_STRING(module->ctx, module->filepath);
-    FREE_STRING(module->ctx, module->org);
-    FREE_STRING(module->ctx, module->contact);
-    FREE_STRING(module->ctx, module->dsc);
-    FREE_STRING(module->ctx, module->ref);
-    FREE_ARRAY(module->ctx, module->off_features, lysc_feature_free);
+    FREE_STRING(ctx, module->name);
+    FREE_STRING(ctx, module->ns);
+    FREE_STRING(ctx, module->prefix);
+    FREE_STRING(ctx, module->filepath);
+    FREE_STRING(ctx, module->org);
+    FREE_STRING(ctx, module->contact);
+    FREE_STRING(ctx, module->dsc);
+    FREE_STRING(ctx, module->ref);
+    FREE_ARRAY(ctx, module->off_features, lysc_feature_free);
 
     memset(module, 0, sizeof *module);
     module->ctx = ctx;
@@ -121,21 +123,22 @@
     *state = test_module;
 
     const char *str;
-    struct lys_parser_ctx ctx = {0};
+    struct lys_parser_ctx *ctx = NULL;
     struct lys_module mod = {0};
     struct lysc_feature *f;
     struct lysc_iffeature *iff;
 
     str = "module test {namespace urn:test; prefix t;"
           "feature f1;feature f2 {if-feature f1;}}";
-    assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, 0, &ctx.ctx));
-    reset_mod(ctx.ctx, &mod);
+    assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, 0, &mod.ctx));
+    reset_mod(&mod);
 
     assert_int_equal(LY_EINVAL, lys_compile(NULL, 0));
     logbuf_assert("Invalid argument mod (lys_compile()).");
     assert_int_equal(LY_EINVAL, lys_compile(&mod, 0));
     logbuf_assert("Invalid argument mod->parsed (lys_compile()).");
     assert_int_equal(LY_SUCCESS, yang_parse_module(&ctx, str, &mod));
+    lys_parser_ctx_free(ctx);
     mod.implemented = 0;
     assert_int_equal(LY_SUCCESS, lys_compile(&mod, 0));
     assert_null(mod.compiled);
@@ -168,20 +171,22 @@
     /* submodules cannot be compiled directly */
     str = "submodule test {belongs-to xxx {prefix x;}}";
     assert_int_equal(LY_EINVAL, yang_parse_module(&ctx, str, &mod));
+    lys_parser_ctx_free(ctx);
     logbuf_assert("Input data contains submodule which cannot be parsed directly without its main module.");
     assert_null(mod.parsed);
-    reset_mod(ctx.ctx, &mod);
+    reset_mod(&mod);
 
     /* data definition name collision in top level */
     assert_int_equal(LY_SUCCESS, yang_parse_module(&ctx, "module aa {namespace urn:aa;prefix aa;"
                                                   "leaf a {type string;} container a{presence x;}}", &mod));
+    lys_parser_ctx_free(ctx);
     assert_int_equal(LY_EVALID, lys_compile(&mod, 0));
     logbuf_assert("Duplicate identifier \"a\" of data definition/RPC/action/Notification statement. /aa:a");
     assert_null(mod.compiled);
-    reset_mod(ctx.ctx, &mod);
+    reset_mod(&mod);
 
     *state = NULL;
-    ly_ctx_destroy(ctx.ctx, NULL);
+    ly_ctx_destroy(mod.ctx, NULL);
 }
 
 static void
@@ -189,7 +194,7 @@
 {
     *state = test_feature;
 
-    struct lys_parser_ctx ctx = {0};
+    struct lys_parser_ctx *ctx = NULL;
     struct lys_module mod = {0}, *modp;
     const char *str;
     struct lysc_feature *f, *f1;
@@ -203,10 +208,11 @@
           "feature f8 {if-feature \"f1 or f2 or f3 or orfeature or andfeature\";}\n"
           "feature f9 {if-feature \"not not f1\";}}";
 
-    assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, 0, &ctx.ctx));
-    reset_mod(ctx.ctx, &mod);
+    assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, 0, &mod.ctx));
+    reset_mod(&mod);
 
     assert_int_equal(LY_SUCCESS, yang_parse_module(&ctx, str, &mod));
+    lys_parser_ctx_free(ctx);
     assert_int_equal(LY_SUCCESS, lys_compile(&mod, 0));
     assert_non_null(mod.compiled);
     assert_non_null(mod.compiled->features);
@@ -283,7 +289,7 @@
     assert_int_equal(1, lys_feature_value(&mod, "f1"));
     assert_int_equal(0, lys_feature_value(&mod, "f2"));
 
-    assert_non_null(modp = lys_parse_mem(ctx.ctx, "module b {namespace urn:b;prefix b;"
+    assert_non_null(modp = lys_parse_mem(mod.ctx, "module b {namespace urn:b;prefix b;"
                                          "feature f1 {if-feature f2;}feature f2;}", LYS_IN_YANG));
     assert_non_null(modp->compiled);
     assert_non_null(modp->compiled->features);
@@ -303,83 +309,91 @@
     assert_int_equal(LY_EINVAL, lys_feature_enable(&mod, "xxx"));
     logbuf_assert("Feature \"xxx\" not found in module \"a\".");
 
-    reset_mod(ctx.ctx, &mod);
+    reset_mod(&mod);
 
     /* some invalid expressions */
     assert_int_equal(LY_SUCCESS, yang_parse_module(&ctx, "module b{yang-version 1.1;namespace urn:b; prefix b; feature f{if-feature f1;}}", &mod));
+    lys_parser_ctx_free(ctx);
     assert_int_equal(LY_EVALID, lys_compile(&mod, 0));
     logbuf_assert("Invalid value \"f1\" of if-feature - unable to find feature \"f1\". /b:{feature='f'}");
-    reset_mod(ctx.ctx, &mod);
+    reset_mod(&mod);
 
     assert_int_equal(LY_SUCCESS, yang_parse_module(&ctx, "module b{yang-version 1.1;namespace urn:b; prefix b; feature f1; feature f2{if-feature 'f and';}}", &mod));
+    lys_parser_ctx_free(ctx);
     assert_int_equal(LY_EVALID, lys_compile(&mod, 0));
     logbuf_assert("Invalid value \"f and\" of if-feature - unexpected end of expression. /b:{feature='f2'}");
-    reset_mod(ctx.ctx, &mod);
+    reset_mod(&mod);
 
     assert_int_equal(LY_SUCCESS, yang_parse_module(&ctx, "module b{yang-version 1.1;namespace urn:b; prefix b; feature f{if-feature 'or';}}", &mod));
+    lys_parser_ctx_free(ctx);
     assert_int_equal(LY_EVALID, lys_compile(&mod, 0));
     logbuf_assert("Invalid value \"or\" of if-feature - unexpected end of expression. /b:{feature='f'}");
-    reset_mod(ctx.ctx, &mod);
+    reset_mod(&mod);
 
     assert_int_equal(LY_SUCCESS, yang_parse_module(&ctx, "module b{yang-version 1.1;namespace urn:b; prefix b; feature f1; feature f2{if-feature '(f1';}}", &mod));
+    lys_parser_ctx_free(ctx);
     assert_int_equal(LY_EVALID, lys_compile(&mod, 0));
     logbuf_assert("Invalid value \"(f1\" of if-feature - non-matching opening and closing parentheses. /b:{feature='f2'}");
-    reset_mod(ctx.ctx, &mod);
+    reset_mod(&mod);
 
     assert_int_equal(LY_SUCCESS, yang_parse_module(&ctx, "module b{yang-version 1.1;namespace urn:b; prefix b; feature f1; feature f2{if-feature 'f1)';}}", &mod));
+    lys_parser_ctx_free(ctx);
     assert_int_equal(LY_EVALID, lys_compile(&mod, 0));
     logbuf_assert("Invalid value \"f1)\" of if-feature - non-matching opening and closing parentheses. /b:{feature='f2'}");
-    reset_mod(ctx.ctx, &mod);
+    reset_mod(&mod);
 
     assert_int_equal(LY_SUCCESS, yang_parse_module(&ctx, "module b{yang-version 1.1;namespace urn:b; prefix b; feature f1; feature f2{if-feature ---;}}", &mod));
+    lys_parser_ctx_free(ctx);
     assert_int_equal(LY_EVALID, lys_compile(&mod, 0));
     logbuf_assert("Invalid value \"---\" of if-feature - unable to find feature \"---\". /b:{feature='f2'}");
-    reset_mod(ctx.ctx, &mod);
+    reset_mod(&mod);
 
     assert_int_equal(LY_SUCCESS, yang_parse_module(&ctx, "module b{namespace urn:b; prefix b; feature f1; feature f2{if-feature 'not f1';}}", &mod));
+    lys_parser_ctx_free(ctx);
     assert_int_equal(LY_EVALID, lys_compile(&mod, 0));
     logbuf_assert("Invalid value \"not f1\" of if-feature - YANG 1.1 expression in YANG 1.0 module. /b:{feature='f2'}");
-    reset_mod(ctx.ctx, &mod);
+    reset_mod(&mod);
 
     assert_int_equal(LY_SUCCESS, yang_parse_module(&ctx, "module b{namespace urn:b; prefix b; feature f1; feature f1;}", &mod));
+    lys_parser_ctx_free(ctx);
     assert_int_equal(LY_EVALID, lys_compile(&mod, 0));
     logbuf_assert("Duplicate identifier \"f1\" of feature statement. /b:{feature='f1'}");
-    reset_mod(ctx.ctx, &mod);
+    reset_mod(&mod);
 
-    ly_ctx_set_module_imp_clb(ctx.ctx, test_imp_clb, "submodule sz {belongs-to z {prefix z;} feature f1;}");
-    assert_null(lys_parse_mem(ctx.ctx, "module z{namespace urn:z; prefix z; include sz;feature f1;}", LYS_IN_YANG));
+    ly_ctx_set_module_imp_clb(mod.ctx, test_imp_clb, "submodule sz {belongs-to z {prefix z;} feature f1;}");
+    assert_null(lys_parse_mem(mod.ctx, "module z{namespace urn:z; prefix z; include sz;feature f1;}", LYS_IN_YANG));
     logbuf_assert("Duplicate identifier \"f1\" of feature statement. /z:{feature='f1'}");
 
-    assert_null(lys_parse_mem(ctx.ctx, "module aa{namespace urn:aa; prefix aa; feature f1 {if-feature f2;} feature f2 {if-feature f1;}}", LYS_IN_YANG));
+    assert_null(lys_parse_mem(mod.ctx, "module aa{namespace urn:aa; prefix aa; feature f1 {if-feature f2;} feature f2 {if-feature f1;}}", LYS_IN_YANG));
     logbuf_assert("Feature \"f1\" is indirectly referenced from itself. /aa:{feature='f2'}");
-    assert_null(lys_parse_mem(ctx.ctx, "module ab{namespace urn:ab; prefix ab; feature f1 {if-feature f1;}}", LYS_IN_YANG));
+    assert_null(lys_parse_mem(mod.ctx, "module ab{namespace urn:ab; prefix ab; feature f1 {if-feature f1;}}", LYS_IN_YANG));
     logbuf_assert("Feature \"f1\" is referenced from itself. /ab:{feature='f1'}");
 
-    assert_null(lys_parse_mem(ctx.ctx, "module bb{yang-version 1.1; namespace urn:bb; prefix bb; feature f {if-feature ();}}", LYS_IN_YANG));
+    assert_null(lys_parse_mem(mod.ctx, "module bb{yang-version 1.1; namespace urn:bb; prefix bb; feature f {if-feature ();}}", LYS_IN_YANG));
     logbuf_assert("Invalid value \"()\" of if-feature - number of features in expression does not match the required number "
             "of operands for the operations. /bb:{feature='f'}");
-    assert_null(lys_parse_mem(ctx.ctx, "module bb{yang-version 1.1; namespace urn:bb; prefix bb; feature f1; feature f {if-feature 'f1(';}}", LYS_IN_YANG));
+    assert_null(lys_parse_mem(mod.ctx, "module bb{yang-version 1.1; namespace urn:bb; prefix bb; feature f1; feature f {if-feature 'f1(';}}", LYS_IN_YANG));
     logbuf_assert("Invalid value \"f1(\" of if-feature - non-matching opening and closing parentheses. /bb:{feature='f'}");
-    assert_null(lys_parse_mem(ctx.ctx, "module bb{yang-version 1.1; namespace urn:bb; prefix bb; feature f1; feature f {if-feature 'and f1';}}", LYS_IN_YANG));
+    assert_null(lys_parse_mem(mod.ctx, "module bb{yang-version 1.1; namespace urn:bb; prefix bb; feature f1; feature f {if-feature 'and f1';}}", LYS_IN_YANG));
     logbuf_assert("Invalid value \"and f1\" of if-feature - missing feature/expression before \"and\" operation. /bb:{feature='f'}");
-    assert_null(lys_parse_mem(ctx.ctx, "module bb{yang-version 1.1; namespace urn:bb; prefix bb; feature f1; feature f {if-feature 'f1 not ';}}", LYS_IN_YANG));
+    assert_null(lys_parse_mem(mod.ctx, "module bb{yang-version 1.1; namespace urn:bb; prefix bb; feature f1; feature f {if-feature 'f1 not ';}}", LYS_IN_YANG));
     logbuf_assert("Invalid value \"f1 not \" of if-feature - unexpected end of expression. /bb:{feature='f'}");
-    assert_null(lys_parse_mem(ctx.ctx, "module bb{yang-version 1.1; namespace urn:bb; prefix bb; feature f1; feature f {if-feature 'f1 not not ';}}", LYS_IN_YANG));
+    assert_null(lys_parse_mem(mod.ctx, "module bb{yang-version 1.1; namespace urn:bb; prefix bb; feature f1; feature f {if-feature 'f1 not not ';}}", LYS_IN_YANG));
     logbuf_assert("Invalid value \"f1 not not \" of if-feature - unexpected end of expression. /bb:{feature='f'}");
-    assert_null(lys_parse_mem(ctx.ctx, "module bb{yang-version 1.1; namespace urn:bb; prefix bb; feature f1; feature f2; "
+    assert_null(lys_parse_mem(mod.ctx, "module bb{yang-version 1.1; namespace urn:bb; prefix bb; feature f1; feature f2; "
                               "feature f {if-feature 'or f1 f2';}}", LYS_IN_YANG));
     logbuf_assert("Invalid value \"or f1 f2\" of if-feature - missing feature/expression before \"or\" operation. /bb:{feature='f'}");
 
     /* import reference */
-    assert_non_null(modp = lys_parse_mem(ctx.ctx, str, LYS_IN_YANG));
+    assert_non_null(modp = lys_parse_mem(mod.ctx, str, LYS_IN_YANG));
     assert_int_equal(LY_SUCCESS, lys_feature_enable(modp, "f1"));
-    assert_non_null(modp = lys_parse_mem(ctx.ctx, "module c{namespace urn:c; prefix c; import a {prefix a;} feature f1; feature f2{if-feature 'a:f1';}}", LYS_IN_YANG));
+    assert_non_null(modp = lys_parse_mem(mod.ctx, "module c{namespace urn:c; prefix c; import a {prefix a;} feature f1; feature f2{if-feature 'a:f1';}}", LYS_IN_YANG));
     assert_int_equal(LY_SUCCESS, lys_feature_enable(modp, "f2"));
     assert_int_equal(0, lys_feature_value(modp, "f1"));
     assert_int_equal(1, lys_feature_value(modp, "f2"));
 
     *state = NULL;
-    ly_ctx_destroy(ctx.ctx, NULL);
+    ly_ctx_destroy(mod.ctx, NULL);
 }
 
 static void