parser FEATURE set of currently parsed modules

... instead of only the last one. It is used
to handle cyclic includes.
diff --git a/src/parser_stmt.c b/src/parser_stmt.c
index 2875b75..4dfda0b 100644
--- a/src/parser_stmt.c
+++ b/src/parser_stmt.c
@@ -168,7 +168,7 @@
     /* allocate new pointer */
     LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *qnames, item, LY_EMEM);
     LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &item->str));
-    item->mod = ctx->parsed_mod;
+    item->mod = PARSER_CUR_PMOD(ctx);
 
     for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
         switch (child->kw) {
@@ -416,7 +416,7 @@
 {
     LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_STR_ARG, stmt->arg));
     LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &restr->arg.str));
-    restr->arg.mod = ctx->parsed_mod;
+    restr->arg.mod = PARSER_CUR_PMOD(ctx);
 
     for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
         switch (child->kw) {
@@ -844,7 +844,7 @@
     buf[0] = LYSP_RESTR_PATTERN_ACK; /* pattern's default regular-match flag */
     buf[arg_len + 1] = '\0'; /* terminating NULL byte */
     LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, &restr->arg.str));
-    restr->arg.mod = ctx->parsed_mod;
+    restr->arg.mod = PARSER_CUR_PMOD(ctx);
 
     for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
         switch (child->kw) {
@@ -898,7 +898,7 @@
 
     LY_CHECK_RET(lysp_stmt_validate_value(ctx, Y_PREF_IDENTIF_ARG, stmt->arg));
     LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), stmt->arg, 0, &type->name));
-    type->pmod = ctx->parsed_mod;
+    type->pmod = PARSER_CUR_PMOD(ctx);
 
     for (const struct lysp_stmt *child = stmt->child; child; child = child->next) {
         switch (child->kw) {
@@ -1005,7 +1005,7 @@
             break;
         case LY_STMT_DEFAULT:
             LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->dflt.str, Y_STR_ARG, &leaf->exts));
-            leaf->dflt.mod = ctx->parsed_mod;
+            leaf->dflt.mod = PARSER_CUR_PMOD(ctx);
             break;
         case LY_STMT_DESCRIPTION:
             LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &leaf->dsc, Y_STR_ARG, &leaf->exts));
@@ -1403,7 +1403,7 @@
         switch (child->kw) {
         case LY_STMT_DEFAULT:
             LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->dflt.str, Y_STR_ARG, &tpdf->exts));
-            tpdf->dflt.mod = ctx->parsed_mod;
+            tpdf->dflt.mod = PARSER_CUR_PMOD(ctx);
             break;
         case LY_STMT_DESCRIPTION:
             LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &tpdf->dsc, Y_STR_ARG, &tpdf->exts));
@@ -2045,7 +2045,7 @@
             break;
         case LY_STMT_DEFAULT:
             LY_CHECK_RET(lysp_stmt_text_field(ctx, child, 0, &choice->dflt.str, Y_PREF_IDENTIF_ARG, &choice->exts));
-            choice->dflt.mod = ctx->parsed_mod;
+            choice->dflt.mod = PARSER_CUR_PMOD(ctx);
             break;
         case LY_STMT_ANYDATA:
             PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "choice");
@@ -2306,9 +2306,15 @@
     LY_ERR ret = LY_SUCCESS;
     uint16_t flags;
     struct lys_parser_ctx pctx = {0};
+    struct ly_set pmods = {0};
+    void *objs;
 
+    /* local context */
     pctx.format = LYS_IN_YANG;
-    pctx.parsed_mod = ctx->pmod;
+    pctx.parsed_mods = &pmods;
+    objs = &ctx->pmod;
+    pmods.objs = objs;
+    pmods.count = 1;
 
     LOG_LOCSET(NULL, NULL, ctx->path, NULL);
 
diff --git a/src/parser_yang.c b/src/parser_yang.c
index 79a1683..692064b 100644
--- a/src/parser_yang.c
+++ b/src/parser_yang.c
@@ -760,8 +760,7 @@
     } else if (*kw == LY_STMT_SYNTAX_LEFT_BRACE) {
         ctx->depth++;
         if (ctx->depth > LY_MAX_BLOCK_DEPTH) {
-            LOGERR(ctx->parsed_mod->mod->ctx, LY_EINVAL,
-                    "The maximum number of block nestings has been exceeded.");
+            LOGERR(PARSER_CTX(ctx), LY_EINVAL, "The maximum number of block nestings has been exceeded.");
             return LY_EINVAL;
         }
         goto success;
@@ -885,7 +884,7 @@
     }
 
     stmt->format = LY_VALUE_SCHEMA;
-    stmt->prefix_data = ctx->parsed_mod;
+    stmt->prefix_data = PARSER_CUR_PMOD(ctx);
     stmt->kw = kw;
 
     YANG_READ_SUBSTMT_FOR(ctx, child_kw, word, word_len, ret, return LY_SUCCESS, return ret) {
@@ -935,7 +934,7 @@
     /* store the rest of information */
     e->format = LY_VALUE_SCHEMA;
     e->parsed = NULL;
-    e->prefix_data = ctx->parsed_mod;
+    e->prefix_data = PARSER_CUR_PMOD(ctx);
     e->parent_stmt = insubstmt;
     e->parent_stmt_index = insubstmt_index;
 
@@ -1064,9 +1063,9 @@
 
     /* get value, it must match the main module */
     LY_CHECK_RET(get_argument(ctx, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
-    if (ly_strncmp(ctx->parsed_mod->mod->name, word, word_len)) {
+    if (ly_strncmp(PARSER_CUR_PMOD(ctx)->mod->name, word, word_len)) {
         LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Submodule \"belongs-to\" value \"%.*s\" does not match its module name \"%s\".",
-                (int)word_len, word, ctx->parsed_mod->mod->name);
+                (int)word_len, word, PARSER_CUR_PMOD(ctx)->mod->name);
         free(buf);
         return LY_EVALID;
     }
@@ -1375,7 +1374,7 @@
     LY_CHECK_RET(get_argument(ctx, arg, NULL, &word, &buf, &word_len));
 
     INSERT_WORD_RET(ctx, buf, item->str, word, word_len);
-    item->mod = ctx->parsed_mod;
+    item->mod = PARSER_CUR_PMOD(ctx);
     YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, return LY_SUCCESS, return ret) {
         switch (kw) {
         case LY_STMT_EXTENSION_INSTANCE:
@@ -1509,7 +1508,7 @@
 
     CHECK_NONEMPTY(ctx, word_len, ly_stmt2str(restr_kw));
     INSERT_WORD_RET(ctx, buf, restr->arg.str, word, word_len);
-    restr->arg.mod = ctx->parsed_mod;
+    restr->arg.mod = PARSER_CUR_PMOD(ctx);
     YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, return LY_SUCCESS, return ret) {
         switch (kw) {
         case LY_STMT_DESCRIPTION:
@@ -2071,7 +2070,7 @@
     buf[0] = LYSP_RESTR_PATTERN_ACK; /* pattern's default regular-match flag */
     buf[word_len + 1] = '\0'; /* terminating NULL byte */
     LY_CHECK_RET(lydict_insert_zc(PARSER_CTX(ctx), buf, &restr->arg.str));
-    restr->arg.mod = ctx->parsed_mod;
+    restr->arg.mod = PARSER_CUR_PMOD(ctx);
 
     YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, return LY_SUCCESS, return ret) {
         switch (kw) {
@@ -2130,7 +2129,7 @@
     INSERT_WORD_RET(ctx, buf, type->name, word, word_len);
 
     /* set module */
-    type->pmod = ctx->parsed_mod;
+    type->pmod = PARSER_CUR_PMOD(ctx);
 
     YANG_READ_SUBSTMT_FOR(ctx, kw, word, word_len, ret, return LY_SUCCESS, return ret) {
         switch (kw) {
@@ -2250,7 +2249,7 @@
             break;
         case LY_STMT_DEFAULT:
             LY_CHECK_RET(parse_text_field(ctx, LY_STMT_DEFAULT, 0, &leaf->dflt.str, Y_STR_ARG, &leaf->exts));
-            leaf->dflt.mod = ctx->parsed_mod;
+            leaf->dflt.mod = PARSER_CUR_PMOD(ctx);
             break;
         case LY_STMT_DESCRIPTION:
             LY_CHECK_RET(parse_text_field(ctx, LY_STMT_DESCRIPTION, 0, &leaf->dsc, Y_STR_ARG, &leaf->exts));
@@ -2663,7 +2662,7 @@
         switch (kw) {
         case LY_STMT_DEFAULT:
             LY_CHECK_RET(parse_text_field(ctx, LY_STMT_DEFAULT, 0, &tpdf->dflt.str, Y_STR_ARG, &tpdf->exts));
-            tpdf->dflt.mod = ctx->parsed_mod;
+            tpdf->dflt.mod = PARSER_CUR_PMOD(ctx);
             break;
         case LY_STMT_DESCRIPTION:
             LY_CHECK_RET(parse_text_field(ctx, LY_STMT_DESCRIPTION, 0, &tpdf->dsc, Y_STR_ARG, &tpdf->exts));
@@ -3339,7 +3338,7 @@
         case LY_STMT_DEFAULT:
             LY_CHECK_RET(parse_text_field(ctx, LY_STMT_DEFAULT, 0, &choice->dflt.str, Y_PREF_IDENTIF_ARG,
                     &choice->exts));
-            choice->dflt.mod = ctx->parsed_mod;
+            choice->dflt.mod = PARSER_CUR_PMOD(ctx);
             break;
 
         case LY_STMT_ANYDATA:
@@ -3849,7 +3848,7 @@
                 return LY_EVALID;
             case LYS_DEV_REPLACE:
                 LY_CHECK_RET(parse_text_field(ctx, LY_STMT_DEFAULT, 0, &d_rpl->dflt.str, Y_STR_ARG, &d->exts));
-                d_rpl->dflt.mod = ctx->parsed_mod;
+                d_rpl->dflt.mod = PARSER_CUR_PMOD(ctx);
                 break;
             default:
                 LY_CHECK_RET(parse_qnames(ctx, LY_STMT_DEFAULT, d_dflts, Y_STR_ARG, &d->exts));
@@ -4091,7 +4090,7 @@
             LY_CHECK_RET(parse_status(ctx, &ident->flags, &ident->exts));
             break;
         case LY_STMT_BASE:
-            if (ident->bases && (ctx->parsed_mod->version < LYS_VERSION_1_1)) {
+            if (ident->bases && (PARSER_CUR_PMOD(ctx)->version < LYS_VERSION_1_1)) {
                 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Identity can be derived from multiple base identities only in YANG 1.1 modules");
                 return LY_EVALID;
             }
@@ -4575,9 +4574,12 @@
 
     mod_p = calloc(1, sizeof *mod_p);
     LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ly_ctx); ret = LY_EMEM, cleanup);
-    mod_p->mod = main_ctx->parsed_mod->mod;
+    mod_p->mod = PARSER_CUR_PMOD(main_ctx)->mod;
     mod_p->parsing = 1;
-    (*context)->parsed_mod = (struct lysp_module *)mod_p;
+
+    /* use main context parsed mods adding the current one */
+    (*context)->parsed_mods = main_ctx->parsed_mods;
+    ly_set_add((*context)->parsed_mods, mod_p, 1, NULL);
 
     LOG_LOCINIT(NULL, NULL, NULL, in);
 
@@ -4639,13 +4641,14 @@
     *context = calloc(1, sizeof **context);
     LY_CHECK_ERR_RET(!(*context), LOGMEM(mod->ctx), LY_EMEM);
     (*context)->format = LYS_IN_YANG;
+    LY_CHECK_ERR_RET(ly_set_new(&(*context)->parsed_mods), free(*context); LOGMEM(mod->ctx), LY_EMEM);
     (*context)->in = in;
     (*context)->main_ctx = (struct lys_parser_ctx *)(*context);
 
     mod_p = calloc(1, sizeof *mod_p);
     LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(mod->ctx), cleanup);
     mod_p->mod = mod;
-    (*context)->parsed_mod = mod_p;
+    ly_set_add((*context)->parsed_mods, mod_p, 1, NULL);
 
     LOG_LOCINIT(NULL, NULL, NULL, in);
 
diff --git a/src/parser_yin.c b/src/parser_yin.c
index e5cb0bf..3ea8f0b 100644
--- a/src/parser_yin.c
+++ b/src/parser_yin.c
@@ -657,7 +657,7 @@
     saved_value[0] = LYSP_RESTR_PATTERN_ACK;
     saved_value[len + 1] = '\0';
     LY_CHECK_RET(lydict_insert_zc(ctx->xmlctx->ctx, saved_value, &restr->arg.str));
-    restr->arg.mod = ctx->parsed_mod;
+    restr->arg.mod = PARSER_CUR_PMOD(ctx);
     type->flags |= LYS_SET_PATTERN;
 
     struct yin_subelement subelems[] = {
@@ -961,7 +961,7 @@
 
     LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
     LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, &restr->arg.str, Y_STR_ARG, restr_kw));
-    restr->arg.mod = ctx->parsed_mod;
+    restr->arg.mod = PARSER_CUR_PMOD(ctx);
 
     return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), restr_kw, NULL, &restr->exts);
 }
@@ -1045,19 +1045,19 @@
             qnames = (struct lysp_qname **)subinfo->dest;
             LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *qnames, qname, LY_EMEM);
         }
-        qname->mod = ctx->parsed_mod;
+        qname->mod = PARSER_CUR_PMOD(ctx);
         return yin_parse_simple_element(ctx, kw, &qname->str, YIN_ARG_VALUE, Y_STR_ARG, exts);
     case LY_STMT_UNIQUE:
         assert(!(subinfo->flags & YIN_SUBELEM_UNIQUE));
         qnames = (struct lysp_qname **)subinfo->dest;
         LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *qnames, qname, LY_EMEM);
-        qname->mod = ctx->parsed_mod;
+        qname->mod = PARSER_CUR_PMOD(ctx);
         return yin_parse_simple_element(ctx, kw, &qname->str, YIN_ARG_TAG, Y_STR_ARG, exts);
     case LY_STMT_IF_FEATURE:
         assert(!(subinfo->flags & YIN_SUBELEM_UNIQUE));
         qnames = (struct lysp_qname **)subinfo->dest;
         LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *qnames, qname, LY_EMEM);
-        qname->mod = ctx->parsed_mod;
+        qname->mod = PARSER_CUR_PMOD(ctx);
         return yin_parse_simple_element(ctx, kw, &qname->str, YIN_ARG_NAME, Y_STR_ARG, exts);
     default:
         break;
@@ -1161,9 +1161,9 @@
 
     LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
     LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_MODULE, &belongsto, Y_IDENTIF_ARG, LY_STMT_BELONGS_TO));
-    if (ctx->parsed_mod->mod->name != belongsto) {
+    if (PARSER_CUR_PMOD(ctx)->mod->name != belongsto) {
         LOGVAL_PARSER(ctx, LYVE_SYNTAX_YIN, "Submodule \"belongs-to\" value \"%s\" does not match its module name \"%s\".",
-                belongsto, ctx->parsed_mod->mod->name);
+                belongsto, PARSER_CUR_PMOD(ctx)->mod->name);
         lydict_remove(ctx->xmlctx->ctx, belongsto);
         return LY_EVALID;
     }
@@ -1255,7 +1255,7 @@
         type = nested_type;
     }
 
-    type->pmod = ctx->parsed_mod;
+    type->pmod = PARSER_CUR_PMOD(ctx);
 
     struct yin_subelement subelems[] = {
         {LY_STMT_BASE, type, 0},
@@ -3333,7 +3333,7 @@
             }
             if (subelem->flags & YIN_SUBELEM_VER2) {
                 /* subelement is supported only in version 1.1 or higher */
-                if (ctx->parsed_mod->version < LYS_VERSION_1_1) {
+                if (PARSER_CUR_PMOD(ctx)->version < LYS_VERSION_1_1) {
                     LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INSUBELEM2, ly_stmt2str(kw), ly_stmt2str(current_element));
                     ret = LY_EVALID;
                     goto cleanup;
@@ -3435,9 +3435,9 @@
                 ret = yin_parse_import(ctx, (struct import_meta *)subelem->dest);
                 break;
             case LY_STMT_INCLUDE:
-                if ((current_element == LY_STMT_SUBMODULE) && (ctx->parsed_mod->version == LYS_VERSION_1_1)) {
+                if ((current_element == LY_STMT_SUBMODULE) && (PARSER_CUR_PMOD(ctx)->version == LYS_VERSION_1_1)) {
                     LOGWRN(PARSER_CTX(ctx), "YANG version 1.1 expects all includes in main module, includes in submodules (%s) are not necessary.",
-                            ((struct lysp_submodule *)(ctx->parsed_mod))->name);
+                            ((struct lysp_submodule *)PARSER_CUR_PMOD(ctx))->name);
                 }
                 ret = yin_parse_include(ctx, (struct include_meta *)subelem->dest);
                 break;
@@ -3717,9 +3717,12 @@
 
     mod_p = calloc(1, sizeof *mod_p);
     LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx); ret = LY_EMEM, cleanup);
-    mod_p->mod = main_ctx->parsed_mod->mod;
+    mod_p->mod = PARSER_CUR_PMOD(main_ctx)->mod;
     mod_p->parsing = 1;
-    (*yin_ctx)->parsed_mod = (struct lysp_module *)mod_p;
+
+    /* use main context parsed mods adding the current one */
+    (*yin_ctx)->parsed_mods = main_ctx->parsed_mods;
+    ly_set_add((*yin_ctx)->parsed_mods, mod_p, 1, NULL);
 
     /* check submodule */
     kw = yin_match_keyword(*yin_ctx, (*yin_ctx)->xmlctx->name, (*yin_ctx)->xmlctx->name_len, (*yin_ctx)->xmlctx->prefix,
@@ -3774,13 +3777,14 @@
     *yin_ctx = calloc(1, sizeof **yin_ctx);
     LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(mod->ctx), LY_EMEM);
     (*yin_ctx)->format = LYS_IN_YIN;
+    LY_CHECK_ERR_RET(ly_set_new(&(*yin_ctx)->parsed_mods), free(*yin_ctx); LOGMEM(mod->ctx), LY_EMEM);
     LY_CHECK_RET(lyxml_ctx_new(mod->ctx, in, &(*yin_ctx)->xmlctx));
     (*yin_ctx)->main_ctx = (struct lys_parser_ctx *)(*yin_ctx);
 
     mod_p = calloc(1, sizeof *mod_p);
     LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(mod->ctx), cleanup);
     mod_p->mod = mod;
-    (*yin_ctx)->parsed_mod = mod_p;
+    ly_set_add((*yin_ctx)->parsed_mods, mod_p, 1, NULL);
 
     /* check module */
     kw = yin_match_keyword(*yin_ctx, (*yin_ctx)->xmlctx->name, (*yin_ctx)->xmlctx->name_len, (*yin_ctx)->xmlctx->prefix,
diff --git a/src/tree_schema_free.c b/src/tree_schema_free.c
index 3f3d753..eb3c563 100644
--- a/src/tree_schema_free.c
+++ b/src/tree_schema_free.c
@@ -1143,6 +1143,10 @@
             ly_set_erase(&ctx->tpdfs_nodes, NULL);
             ly_set_erase(&ctx->grps_nodes, NULL);
         }
+        ly_set_rm_index(ctx->parsed_mods, ctx->parsed_mods->count - 1, NULL);
+        if (!ctx->parsed_mods->count) {
+            ly_set_free(ctx->parsed_mods, NULL);
+        }
         free(ctx);
     }
 }
@@ -1155,6 +1159,10 @@
             ly_set_erase(&ctx->tpdfs_nodes, NULL);
             ly_set_erase(&ctx->grps_nodes, NULL);
         }
+        ly_set_rm_index(ctx->parsed_mods, ctx->parsed_mods->count - 1, NULL);
+        if (!ctx->parsed_mods->count) {
+            ly_set_free(ctx->parsed_mods, NULL);
+        }
         lyxml_ctx_free(ctx->xmlctx);
         free(ctx);
     }
diff --git a/src/tree_schema_helpers.c b/src/tree_schema_helpers.c
index 67076b6..b6e3b7a 100644
--- a/src/tree_schema_helpers.c
+++ b/src/tree_schema_helpers.c
@@ -1035,10 +1035,10 @@
  * @return LY_EVALID - YANG rule violation
  */
 static LY_ERR
-lysp_get_submodule(struct lys_parser_ctx *pctx, struct lysp_include *inc)
+lysp_main_pmod_get_submodule(struct lys_parser_ctx *pctx, struct lysp_include *inc)
 {
     LY_ARRAY_COUNT_TYPE i;
-    struct lysp_module *main_pmod = pctx->parsed_mod->mod->parsed;
+    struct lysp_module *main_pmod = PARSER_CUR_PMOD(pctx)->mod->parsed;
 
     LY_ARRAY_FOR(main_pmod->includes, i) {
         if (strcmp(main_pmod->includes[i].name, inc->name)) {
@@ -1048,7 +1048,7 @@
         if (inc->rev[0] && strncmp(inc->rev, main_pmod->includes[i].rev, LY_REV_SIZE)) {
             LOGVAL(PARSER_CTX(pctx), LYVE_REFERENCE,
                     "Submodule %s includes different revision (%s) of the submodule %s:%s included by the main module %s.",
-                    ((struct lysp_submodule *)pctx->parsed_mod)->name, inc->rev,
+                    ((struct lysp_submodule *)PARSER_CUR_PMOD(pctx))->name, inc->rev,
                     main_pmod->includes[i].name, main_pmod->includes[i].rev, main_pmod->mod->name);
             return LY_EVALID;
         }
@@ -1061,7 +1061,7 @@
         LOGVAL(PARSER_CTX(pctx), LYVE_REFERENCE,
                 "YANG 1.1 requires all submodules to be included from main module. "
                 "But submodule \"%s\" includes submodule \"%s\" which is not included by main module \"%s\".",
-                ((struct lysp_submodule *)pctx->parsed_mod)->name, inc->name, main_pmod->mod->name);
+                ((struct lysp_submodule *)PARSER_CUR_PMOD(pctx))->name, inc->name, main_pmod->mod->name);
         return LY_EVALID;
     } else {
         return LY_ENOT;
@@ -1069,6 +1069,46 @@
 }
 
 /**
+ * @brief Try to find the parsed submodule in currenlty parsed modules for the given include record.
+ *
+ * @param[in] pctx main parser context
+ * @param[in] inc The include record with missing parsed submodule.
+ * @return LY_SUCCESS - the parsed submodule was found and inserted into the @p inc record
+ * @return LY_ENOT - the parsed module was not found.
+ * @return LY_EVALID - YANG rule violation
+ */
+static LY_ERR
+lysp_parsed_mods_get_submodule(struct lys_parser_ctx *pctx, struct lysp_include *inc)
+{
+    uint32_t i;
+    struct lysp_submodule *submod;
+
+    for (i = 0; i < pctx->parsed_mods->count - 1; ++i) {
+        submod = pctx->parsed_mods->objs[i];
+        if (!submod->is_submod) {
+            continue;
+        }
+
+        if (strcmp(submod->name, inc->name)) {
+            continue;
+        }
+
+        if (inc->rev[0] && submod->revs && strncmp(inc->rev, submod->revs[0].date, LY_REV_SIZE)) {
+            LOGVAL(PARSER_CTX(pctx), LYVE_REFERENCE,
+                    "Submodule %s includes different revision (%s) of the submodule %s:%s included by the main module %s.",
+                    ((struct lysp_submodule *)PARSER_CUR_PMOD(pctx))->name, inc->rev,
+                    submod->name, submod->revs[0].date, PARSER_CUR_PMOD(pctx)->mod->name);
+            return LY_EVALID;
+        }
+
+        inc->submodule = submod;
+        return LY_SUCCESS;
+    }
+
+    return LY_ENOT;
+}
+
+/**
  * @brief Make the copy of the given include record into the main module.
  *
  * YANG 1.0 does not require the main module to include all the submodules. Therefore, parsing submodules can cause
@@ -1083,7 +1123,7 @@
 {
     LY_ARRAY_COUNT_TYPE i;
     struct lysp_include *inc_new, *inc_tofill = NULL;
-    struct lysp_module *main_pmod = pctx->parsed_mod->mod->parsed;
+    struct lysp_module *main_pmod = PARSER_CUR_PMOD(pctx)->mod->parsed;
 
     /* first, try to find the corresponding record with missing parsed submodule */
     LY_ARRAY_FOR(main_pmod->includes, i) {
@@ -1117,7 +1157,7 @@
     struct ly_ctx *ctx = PARSER_CTX(pctx);
 
     LY_ARRAY_FOR(pmod->includes, u) {
-        LY_ERR ret = LY_SUCCESS;
+        LY_ERR ret = LY_SUCCESS, r;
         struct lysp_submodule *submod = NULL;
         struct lysp_include *inc = &pmod->includes[u];
 
@@ -1127,11 +1167,14 @@
 
         if (pmod->is_submod) {
             /* try to find the submodule in the main module or its submodules */
-            ret = lysp_get_submodule(pctx, inc);
-            LY_CHECK_RET(ret && ret != LY_ENOT, ret);
-            LY_CHECK_RET(ret == LY_SUCCESS, LY_SUCCESS); /* submodule found in linked with the inc */
+            ret = lysp_main_pmod_get_submodule(pctx, inc);
+            LY_CHECK_RET(ret != LY_ENOT, ret);
         }
 
+        /* try to use currently parsed submodule */
+        r = lysp_parsed_mods_get_submodule(pctx, inc);
+        LY_CHECK_RET(r != LY_ENOT, r);
+
         /* submodule not present in the main module, get the input data and parse it */
         if (!(ctx->flags & LY_CTX_PREFER_SEARCHDIRS)) {
 search_clb:
@@ -1142,13 +1185,13 @@
                 struct lysp_load_module_check_data check_data = {0};
                 struct ly_in *in;
 
-                if (ctx->imp_clb(pctx->parsed_mod->mod->name, NULL, inc->name,
+                if (ctx->imp_clb(PARSER_CUR_PMOD(pctx)->mod->name, NULL, inc->name,
                         inc->rev[0] ? inc->rev : NULL, ctx->imp_clb_data,
                         &format, &submodule_data, &submodule_data_free) == LY_SUCCESS) {
                     LY_CHECK_RET(ly_in_new_memory(submodule_data, &in));
                     check_data.name = inc->name;
                     check_data.revision = inc->rev[0] ? inc->rev : NULL;
-                    check_data.submoduleof = pctx->parsed_mod->mod->name;
+                    check_data.submoduleof = PARSER_CUR_PMOD(pctx)->mod->name;
                     lys_parse_submodule(ctx, in, format, pctx, lysp_load_module_check, &check_data, new_mods, &submod);
 
                     /* update inc pointer - parsing another (YANG 1.0) submodule can cause injecting
@@ -1169,7 +1212,7 @@
             if (!(ctx->flags & LY_CTX_DISABLE_SEARCHDIRS)) {
                 /* submodule was not received from the callback or there is no callback set */
                 lys_parse_localfile(ctx, inc->name, inc->rev[0] ? inc->rev : NULL, pctx,
-                        pctx->parsed_mod->mod->name, 1, new_mods, (void **)&submod);
+                        PARSER_CUR_PMOD(pctx)->mod->name, 1, new_mods, (void **)&submod);
 
                 /* update inc pointer - parsing another (YANG 1.0) submodule can cause injecting
                  * submodule's include into main module, where it is missing */
@@ -1194,7 +1237,8 @@
         }
         if (!inc->submodule) {
             LOGVAL(ctx, LYVE_REFERENCE, "Including \"%s\" submodule into \"%s\" failed.", inc->name,
-                    pctx->parsed_mod->is_submod ? ((struct lysp_submodule *)pctx->parsed_mod)->name : pctx->parsed_mod->mod->name);
+                    PARSER_CUR_PMOD(pctx)->is_submod ? ((struct lysp_submodule *)PARSER_CUR_PMOD(pctx))->name :
+                    PARSER_CUR_PMOD(pctx)->mod->name);
             return LY_EVALID;
         }
     }
diff --git a/src/tree_schema_internal.h b/src/tree_schema_internal.h
index ffea7a2..e28f69b 100644
--- a/src/tree_schema_internal.h
+++ b/src/tree_schema_internal.h
@@ -67,7 +67,7 @@
  * @param[in] PARENT parent statement where the KW is present - for logging.
  */
 #define PARSER_CHECK_STMTVER2_RET(CTX, KW, PARENT) \
-    if ((CTX)->parsed_mod->version < LYS_VERSION_1_1) {LOGVAL_PARSER((CTX), LY_VCODE_INCHILDSTMT2, KW, PARENT); return LY_EVALID;}
+    if (PARSER_CUR_PMOD(CTX)->version < LYS_VERSION_1_1) {LOGVAL_PARSER((CTX), LY_VCODE_INCHILDSTMT2, KW, PARENT); return LY_EVALID;}
 
 /* These 2 macros checks YANG's identifier grammar rule */
 #define is_yangidentstartchar(c) ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_')
@@ -138,7 +138,8 @@
     Y_MAYBE_STR_ARG       /**< optional YANG "string" rule */
 };
 
-#define PARSER_CTX(CTX) ((CTX)->parsed_mod->mod->ctx)
+#define PARSER_CUR_PMOD(CTX) ((struct lysp_module *)(CTX)->parsed_mods->objs[(CTX)->parsed_mods->count - 1])
+#define PARSER_CTX(CTX) (PARSER_CUR_PMOD(CTX)->mod->ctx)
 #define LOGVAL_PARSER(CTX, ...) LOGVAL((CTX) ? PARSER_CTX(CTX) : NULL, __VA_ARGS__)
 
 struct lys_parser_ctx {
@@ -147,7 +148,7 @@
                                           submodule, use ::lys_parser_ctx.main_ctx instead. */
     struct ly_set grps_nodes;        /**< Set of nodes that contain grouping(s). Invalid in case of
                                           submodule, use ::lys_parser_ctx.main_ctx instead. */
-    struct lysp_module *parsed_mod;  /**< (sub)module being parsed */
+    struct ly_set *parsed_mods;      /**< (sub)modules being parsed, the last one is the current */
     struct lys_parser_ctx *main_ctx; /**< This pointer must not be NULL. If this context deals with the submodule,
                                           then should be set to the context of the module to which it belongs,
                                           otherwise it points to the beginning of this structure. */
@@ -162,7 +163,7 @@
                                           submodule, use ::lys_parser_ctx.main_ctx instead. */
     struct ly_set grps_nodes;        /**< Set of nodes that contain grouping(s). Invalid in case of
                                           submodule, use ::lys_parser_ctx.main_ctx instead. */
-    struct lysp_module *parsed_mod;  /**< (sub)module being parsed */
+    struct ly_set *parsed_mods;      /**< (sub)modules being parsed, the last one is the current */
     struct lys_parser_ctx *main_ctx; /**< This pointer must not be NULL. If this context deals with the submodule,
                                           then should be set to the context of the module to which it belongs,
                                           otherwise it points to the beginning of this structure. */
@@ -185,7 +186,7 @@
                                           submodule, use ::lys_parser_ctx.main_ctx instead. */
     struct ly_set grps_nodes;        /**< Set of nodes that contain grouping(s). Invalid in case of
                                           submodule, use ::lys_parser_ctx.main_ctx instead. */
-    struct lysp_module *parsed_mod;  /**< (sub)module being parsed */
+    struct ly_set *parsed_mods;      /**< (sub)modules being parsed, the last one is the current */
     struct lys_parser_ctx *main_ctx; /**< This pointer must not be NULL. If this context deals with the submodule,
                                           then should be set to the context of the module to which it belongs,
                                           otherwise it points to the beginning of this structure. */