libyang REFACTOR parsed/printed bytes in in/out structs
diff --git a/src/parser_yang.c b/src/parser_yang.c
index 8652a40..104786c 100644
--- a/src/parser_yang.c
+++ b/src/parser_yang.c
@@ -11,6 +11,7 @@
  *
  *     https://opensource.org/licenses/BSD-3-Clause
  */
+#include "parser_internal.h"
 
 #include <assert.h>
 #include <ctype.h>
@@ -44,18 +45,18 @@
     else {(TARGET) = lydict_insert((CTX)->ctx, LEN ? WORD : "", LEN);}
 
 /**
- * @brief Move the DATA pointer by COUNT items. Also updates the indent value in yang parser context
+ * @brief Read from the IN structure COUNT items. Also updates the indent value in yang parser context
  * @param[in] CTX yang parser context to update its indent value.
- * @param[in,out] DATA pointer to move
+ * @param[in,out] IN input structure
  * @param[in] COUNT number of items for which the DATA pointer is supposed to move on.
  */
-#define MOVE_INPUT(CTX, DATA, COUNT) (*(DATA))+=COUNT;(CTX)->indent+=COUNT
+#define MOVE_INPUT(CTX, IN, COUNT) ly_in_skip(IN, COUNT);(CTX)->indent+=COUNT
 
 /**
  * @brief Loop through all substatements providing, return if there are none.
  *
  * @param[in] CTX yang parser context for logging.
- * @param[in] DATA Raw data to read from.
+ * @param[in] IN Input structure to read from.
  * @param[out] KW YANG keyword read.
  * @param[out] WORD Pointer to the keyword itself.
  * @param[out] WORD_LEN Length of the keyword.
@@ -63,8 +64,8 @@
  *
  * @return In case there are no substatements or a fatal error encountered.
  */
-#define YANG_READ_SUBSTMT_FOR(CTX, DATA, KW, WORD, WORD_LEN, ERR, CHECKGOTO) \
-    LY_CHECK_RET(get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN)); \
+#define YANG_READ_SUBSTMT_FOR(CTX, IN, KW, WORD, WORD_LEN, ERR, CHECKGOTO) \
+    LY_CHECK_RET(get_keyword(CTX, IN, &KW, &WORD, &WORD_LEN)); \
     if (KW == LY_STMT_SYNTAX_SEMICOLON) { \
         CHECKGOTO; \
         return LY_SUCCESS; \
@@ -73,16 +74,17 @@
         LOGVAL_PARSER(CTX, LYVE_SYNTAX_YANG, "Invalid keyword \"%s\", expected \";\" or \"{\".", ly_stmt2str(KW)); \
         return LY_EVALID; \
     } \
-    for (ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN); \
+    for (ERR = get_keyword(CTX, IN, &KW, &WORD, &WORD_LEN); \
             !ERR && (KW != LY_STMT_SYNTAX_RIGHT_BRACE); \
-            ERR = get_keyword(CTX, DATA, &KW, &WORD, &WORD_LEN))
+            ERR = get_keyword(CTX, IN, &KW, &WORD, &WORD_LEN))
 
-LY_ERR parse_container(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
-LY_ERR parse_uses(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
-LY_ERR parse_choice(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
-LY_ERR parse_case(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
-LY_ERR parse_list(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
-LY_ERR parse_grouping(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_grp **groupings);
+LY_ERR parse_container(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_node *parent,
+                       struct lysp_node **siblings);
+LY_ERR parse_uses(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_node *parent, struct lysp_node **siblings);
+LY_ERR parse_choice(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_node *parent, struct lysp_node **siblings);
+LY_ERR parse_case(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_node *parent, struct lysp_node **siblings);
+LY_ERR parse_list(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_node *parent, struct lysp_node **siblings);
+LY_ERR parse_grouping(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_node *parent, struct lysp_grp **groupings);
 
 /**
  * @brief Add another character to dynamic buffer, a low-level function.
@@ -90,7 +92,7 @@
  * Enlarge if needed. Updates \p input as well as \p buf_used.
  *
  * @param[in] ctx libyang context for logging.
- * @param[in, out] input Input string to process.
+ * @param[in,out] in Input structure.
  * @param[in] len Number of bytes to get from the input string and copy into the buffer.
  * @param[in,out] buf Buffer to use, can be moved by realloc().
  * @param[in,out] buf_len Current size of the buffer.
@@ -99,7 +101,7 @@
  * @return LY_ERR values.
  */
 LY_ERR
-buf_add_char(struct ly_ctx *ctx, const char **input, size_t len, char **buf, size_t *buf_len, size_t *buf_used)
+buf_add_char(struct ly_ctx *ctx, struct ly_in *in, size_t len, char **buf, size_t *buf_len, size_t *buf_used)
 {
     if (*buf_len <= (*buf_used) + len) {
         *buf_len += 16;
@@ -107,14 +109,12 @@
         LY_CHECK_ERR_RET(!*buf, LOGMEM(ctx), LY_EMEM);
     }
     if (*buf_used) {
-        memcpy(&(*buf)[*buf_used], *input, len);
+        ly_in_read(in, &(*buf)[*buf_used], len);
     } else {
-        memcpy(*buf, *input, len);
+        ly_in_read(in, *buf, len);
     }
 
     (*buf_used) += len;
-    (*input) += len;
-
     return LY_SUCCESS;
 }
 
@@ -122,8 +122,7 @@
  * @brief Store a single UTF8 character. It depends whether in a dynamically-allocated buffer or just as a pointer to the data.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] input Pointer to the string where to get the character to store. Automatically moved to the next character
- * when function returns.
+ * @param[in,out] in Input structure.
  * @param[in] arg Type of the input string to select method of checking character validity.
  * @param[in,out] word_p Word pointer. If buffer (\p word_b) was not yet needed, it is just a pointer to the first
  * stored character. If buffer was needed (\p word_b is non-NULL or \p need_buf is set), it is pointing to the buffer.
@@ -139,8 +138,8 @@
  * @return LY_ERR values.
  */
 LY_ERR
-buf_store_char(struct lys_yang_parser_ctx *ctx, const char **input, enum yang_arg arg, char **word_p,
-               size_t *word_len, char **word_b, size_t *buf_len, int need_buf, int *prefix)
+buf_store_char(struct lys_yang_parser_ctx *ctx, struct ly_in *in, enum yang_arg arg, char **word_p, size_t *word_len,
+               char **word_b, size_t *buf_len, int need_buf, int *prefix)
 {
     unsigned int c;
     size_t len;
@@ -149,9 +148,9 @@
     assert(!need_buf || (need_buf && word_b));
 
     /* get UTF8 code point (and number of bytes coding the character) */
-    LY_CHECK_ERR_RET(ly_getutf8(input, &c, &len),
-                     LOGVAL_PARSER(ctx, LY_VCODE_INCHAR, (*input)[-len]), LY_EVALID);
-    (*input) -= len;
+    LY_CHECK_ERR_RET(ly_getutf8(&in->current, &c, &len),
+                     LOGVAL_PARSER(ctx, LY_VCODE_INCHAR, in->current[-len]), LY_EVALID);
+    in->current -= len;
     if (c == '\n') {
         ctx->indent = 0;
     } else {
@@ -175,7 +174,7 @@
 
     if (word_b && *word_b) {
         /* add another character into buffer */
-        if (buf_add_char(ctx->ctx, input, len, word_b, buf_len, word_len)) {
+        if (buf_add_char(ctx->ctx, in, len, word_b, buf_len, word_len)) {
             return LY_EMEM;
         }
 
@@ -191,7 +190,7 @@
         }
 
         /* add this new character into buffer */
-        if (buf_add_char(ctx->ctx, input, len, word_b, buf_len, word_len)) {
+        if (buf_add_char(ctx->ctx, in, len, word_b, buf_len, word_len)) {
             return LY_EMEM;
         }
 
@@ -200,11 +199,11 @@
     } else {
         /* just remember the first character pointer */
         if (!*word_p) {
-            *word_p = (char *)(*input);
+            *word_p = (char *)in->current;
         }
         /* ... and update the word's length */
         (*word_len) += len;
-        (*input) += len;
+        ly_in_skip(in, len);
     }
 
     return LY_SUCCESS;
@@ -214,41 +213,40 @@
  * @brief Skip YANG comment in data.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, automatically moved after the comment.
+ * @param[in,out] in Input structure.
  * @param[in] comment Type of the comment to process:
  *                    1 for a one-line comment,
  *                    2 for a block comment.
- *
  * @return LY_ERR values.
  */
 LY_ERR
-skip_comment(struct lys_yang_parser_ctx *ctx, const char **data, int comment)
+skip_comment(struct lys_yang_parser_ctx *ctx, struct ly_in *in, int comment)
 {
     /* internal statuses: 0 - comment ended,
      *                    1 - in line comment,
      *                    2 - in block comment,
      *                    3 - in block comment with last read character '*'
      */
-    while (**data && comment) {
+    while (in->current[0] && comment) {
         switch (comment) {
         case 1:
-            if (**data == '\n') {
+            if (in->current[0] == '\n') {
                 comment = 0;
                 ++ctx->line;
             }
             break;
         case 2:
-            if (**data == '*') {
+            if (in->current[0] == '*') {
                 comment = 3;
-            } else if (**data == '\n') {
+            } else if (in->current[0] == '\n') {
                 ++ctx->line;
             }
             break;
         case 3:
-            if (**data == '/') {
+            if (in->current[0] == '/') {
                 comment = 0;
-            } else if (**data != '*') {
-                if (**data == '\n') {
+            } else if (in->current[0] != '*') {
+                if (in->current[0] == '\n') {
                     ++ctx->line;
                 }
                 comment = 2;
@@ -258,15 +256,15 @@
             LOGINT_RET(ctx->ctx);
         }
 
-        if (**data == '\n') {
+        if (in->current[0] == '\n') {
             ctx->indent = 0;
         } else {
             ++ctx->indent;
         }
-        ++(*data);
+        ++in->current;
     }
 
-    if (!**data && (comment > 1)) {
+    if (!in->current[0] && (comment > 1)) {
         LOGVAL_PARSER(ctx, LYVE_SYNTAX, "Unexpected end-of-input, non-terminated comment.");
         return LY_EVALID;
     }
@@ -278,7 +276,7 @@
  * @brief Read a quoted string from data.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in] arg Type of YANG keyword argument expected.
  * @param[out] word_p Pointer to the read quoted string.
  * @param[out] word_b Pointer to a dynamically-allocated buffer holding the read quoted string. If not needed,
@@ -291,7 +289,7 @@
  * @return LY_ERR values.
  */
 static LY_ERR
-read_qstring(struct lys_yang_parser_ctx *ctx, const char **data, enum yang_arg arg, char **word_p, char **word_b,
+read_qstring(struct lys_yang_parser_ctx *ctx, struct ly_in *in, enum yang_arg arg, char **word_p, char **word_b,
              size_t *word_len, size_t *buf_len)
 {
     /* string: 0 - string ended, 1 - string with ', 2 - string with ", 3 - string with " with last character \,
@@ -302,36 +300,36 @@
     int prefix = 0;
     unsigned int trailing_ws = 0; /* current number of stored trailing whitespace characters */
 
-    if (**data == '\"') {
+    if (in->current[0] == '\"') {
         string = 2;
         current_indent = block_indent = ctx->indent + 1;
     } else {
-        assert(**data == '\'');
+        assert(in->current[0] == '\'');
         string = 1;
     }
-    MOVE_INPUT(ctx, data, 1);
+    MOVE_INPUT(ctx, in, 1);
 
-    while (**data && string) {
+    while (in->current[0] && string) {
         switch (string) {
         case 1:
-            switch (**data) {
+            switch (in->current[0]) {
             case '\'':
                 /* string may be finished, but check for + */
                 string = 4;
-                MOVE_INPUT(ctx, data, 1);
+                MOVE_INPUT(ctx, in, 1);
                 break;
             default:
                 /* check and store character */
-                LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf, &prefix));
+                LY_CHECK_RET(buf_store_char(ctx, in, arg, word_p, word_len, word_b, buf_len, need_buf, &prefix));
                 break;
             }
             break;
         case 2:
-            switch (**data) {
+            switch (in->current[0]) {
             case '\"':
                 /* string may be finished, but check for + */
                 string = 4;
-                MOVE_INPUT(ctx, data, 1);
+                MOVE_INPUT(ctx, in, 1);
                 trailing_ws = 0;
                 break;
             case '\\':
@@ -342,7 +340,7 @@
                 need_buf = 1;
 
                 /* move forward to the escaped character */
-                ++(*data);
+                ++in->current;
 
                 /* note that the trailing whitespaces are supposed to be trimmed before substitution of
                  * backslash-escaped characters (RFC 7950, 6.1.3), so we have to zero the trailing whitespaces counter */
@@ -354,10 +352,10 @@
             case ' ':
                 if (current_indent < block_indent) {
                     ++current_indent;
-                    MOVE_INPUT(ctx, data, 1);
+                    MOVE_INPUT(ctx, in, 1);
                 } else {
                     /* check and store whitespace character */
-                    LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf, &prefix));
+                    LY_CHECK_RET(buf_store_char(ctx, in, arg, word_p, word_len, word_b, buf_len, need_buf, &prefix));
                     trailing_ws++;
                 }
                 break;
@@ -368,14 +366,16 @@
                     ctx->indent += 8;
                     for (; current_indent > block_indent; --current_indent, --ctx->indent) {
                         /* store leftover spaces from the tab */
-                        c = " ";
-                        LY_CHECK_RET(buf_store_char(ctx, &c, arg, word_p, word_len, word_b, buf_len, need_buf, &prefix));
+                        c = in->current;
+                        in->current = " ";
+                        LY_CHECK_RET(buf_store_char(ctx, in, arg, word_p, word_len, word_b, buf_len, need_buf, &prefix));
+                        in->current = c;
                         trailing_ws++;
                     }
-                    ++(*data);
+                    ++in->current;
                 } else {
                     /* check and store whitespace character */
-                    LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf, &prefix));
+                    LY_CHECK_RET(buf_store_char(ctx, in, arg, word_p, word_len, word_b, buf_len, need_buf, &prefix));
                     trailing_ws++;
                     /* additional characters for indentation - only 1 was count in buf_store_char */
                     ctx->indent += 7;
@@ -394,7 +394,7 @@
                 }
 
                 /* check and store character */
-                LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf, &prefix));
+                LY_CHECK_RET(buf_store_char(ctx, in, arg, word_p, word_len, word_b, buf_len, need_buf, &prefix));
 
                 /* maintain line number */
                 ++ctx->line;
@@ -408,39 +408,39 @@
                 current_indent = block_indent;
 
                 /* check and store character */
-                LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, buf_len, need_buf, &prefix));
+                LY_CHECK_RET(buf_store_char(ctx, in, arg, word_p, word_len, word_b, buf_len, need_buf, &prefix));
                 trailing_ws = 0;
                 break;
             }
             break;
         case 3:
             /* string encoded characters */
-            switch (**data) {
+            c = in->current;
+            switch (in->current[0]) {
             case 'n':
-                c = "\n";
+                in->current = "\n";
                 break;
             case 't':
-                c = "\t";
+                in->current = "\t";
                 break;
             case '\"':
-                c = *data;
-                break;
             case '\\':
-                c = *data;
+                /* ok as is */
                 break;
             default:
-                LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Double-quoted string unknown special character '\\%c'.", **data);
+                LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Double-quoted string unknown special character '\\%c'.",
+                              in->current[0]);
                 return LY_EVALID;
             }
 
             /* check and store character */
-            LY_CHECK_RET(buf_store_char(ctx, &c, arg, word_p, word_len, word_b, buf_len, need_buf, &prefix));
+            LY_CHECK_RET(buf_store_char(ctx, in, arg, word_p, word_len, word_b, buf_len, need_buf, &prefix));
 
             string = 2;
-            ++(*data);
+            in->current = c + 1;
             break;
         case 4:
-            switch (**data) {
+            switch (in->current[0]) {
             case '+':
                 /* string continues */
                 string = 5;
@@ -457,10 +457,10 @@
                 /* string is finished */
                 goto string_end;
             }
-            MOVE_INPUT(ctx, data, 1);
+            MOVE_INPUT(ctx, in, 1);
             break;
         case 5:
-            switch (**data) {
+            switch (in->current[0]) {
             case '\n':
                 ++ctx->line;
                 /* fallthrough */
@@ -479,7 +479,7 @@
                 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Both string parts divided by '+' must be quoted.");
                 return LY_EVALID;
             }
-            MOVE_INPUT(ctx, data, 1);
+            MOVE_INPUT(ctx, in, 1);
             break;
         default:
             return LY_EINT;
@@ -499,7 +499,7 @@
  * @brief Get another YANG string from the raw data.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in] arg Type of YANG keyword argument expected.
  * @param[out] flags optional output argument to get flag of the argument's quoting (LYS_*QOUTED - see [schema node flags](@ref snodeflags))
  * @param[out] word_p Pointer to the read string. Can return NULL if \p arg is #Y_MAYBE_STR_ARG.
@@ -510,8 +510,8 @@
  * @return LY_ERR values.
  */
 LY_ERR
-get_argument(struct lys_yang_parser_ctx *ctx, const char **data, enum yang_arg arg,
-             uint16_t *flags, char **word_p, char **word_b, size_t *word_len)
+get_argument(struct lys_yang_parser_ctx *ctx, struct ly_in *in, enum yang_arg arg, uint16_t *flags, char **word_p,
+             char **word_b, size_t *word_len)
 {
     size_t buf_len = 0;
     int prefix = 0;
@@ -522,33 +522,33 @@
     *word_p = NULL;
 
     *word_len = 0;
-    while (**data) {
-        switch (**data) {
+    while (in->current[0]) {
+        switch (in->current[0]) {
         case '\'':
         case '\"':
             if (*word_len) {
                 /* invalid - quotes cannot be in unquoted string and only optsep, ; or { can follow it */
-                LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, 1, *data,
+                LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, 1, in->current,
                             "unquoted string character, optsep, semicolon or opening brace");
                 return LY_EVALID;
             }
             if (flags) {
-                (*flags) |= (**data) == '\'' ? LYS_SINGLEQUOTED : LYS_DOUBLEQUOTED;
+                (*flags) |= in->current[0] == '\'' ? LYS_SINGLEQUOTED : LYS_DOUBLEQUOTED;
             }
-            LY_CHECK_RET(read_qstring(ctx, data, arg, word_p, word_b, word_len, &buf_len));
+            LY_CHECK_RET(read_qstring(ctx, in, arg, word_p, word_b, word_len, &buf_len));
             goto str_end;
         case '/':
-            if ((*data)[1] == '/') {
+            if (in->current[1] == '/') {
                 /* one-line comment */
-                MOVE_INPUT(ctx, data, 2);
-                LY_CHECK_RET(skip_comment(ctx, data, 1));
-            } else if ((*data)[1] == '*') {
+                MOVE_INPUT(ctx, in, 2);
+                LY_CHECK_RET(skip_comment(ctx, in, 1));
+            } else if (in->current[1] == '*') {
                 /* block comment */
-                MOVE_INPUT(ctx, data, 2);
-                LY_CHECK_RET(skip_comment(ctx, data, 2));
+                MOVE_INPUT(ctx, in, 2);
+                LY_CHECK_RET(skip_comment(ctx, in, 2));
             } else {
                 /* not a comment after all */
-                LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, &buf_len, 0, &prefix));
+                LY_CHECK_RET(buf_store_char(ctx, in, arg, word_p, word_len, word_b, &buf_len, 0, &prefix));
             }
             break;
         case ' ':
@@ -556,7 +556,7 @@
                 /* word is finished */
                 goto str_end;
             }
-            MOVE_INPUT(ctx, data, 1);
+            MOVE_INPUT(ctx, in, 1);
             break;
         case '\t':
             if (*word_len) {
@@ -566,7 +566,7 @@
             /* tabs count for 8 spaces */
             ctx->indent += 8;
 
-            ++(*data);
+            ++in->current;
             break;
         case '\n':
             if (*word_len) {
@@ -579,7 +579,7 @@
             /* track line numbers */
             ++ctx->line;
 
-            ++(*data);
+            ++in->current;
             break;
         case ';':
         case '{':
@@ -588,15 +588,15 @@
                 goto str_end;
             }
 
-            LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, 1, *data, "an argument");
+            LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, 1, in->current, "an argument");
             return LY_EVALID;
         case '}':
             /* invalid - braces cannot be in unquoted string (opening braces terminates the string and can follow it) */
-            LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, 1, *data,
+            LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, 1, in->current,
                         "unquoted string character, optsep, semicolon or opening brace");
             return LY_EVALID;
         default:
-            LY_CHECK_RET(buf_store_char(ctx, data, arg, word_p, word_len, word_b, &buf_len, 0, &prefix));
+            LY_CHECK_RET(buf_store_char(ctx, in, arg, word_p, word_len, word_b, &buf_len, 0, &prefix));
             break;
         }
     }
@@ -621,7 +621,7 @@
  * @brief Get another YANG keyword from the raw data.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[out] kw YANG keyword read.
  * @param[out] word_p Pointer to the keyword in the data. Useful for extension instances.
  * @param[out] word_len Length of the keyword in the data. Useful for extension instances.
@@ -629,7 +629,7 @@
  * @return LY_ERR values.
  */
 LY_ERR
-get_keyword(struct lys_yang_parser_ctx *ctx, const char **data, enum ly_stmt *kw, char **word_p, size_t *word_len)
+get_keyword(struct lys_yang_parser_ctx *ctx, struct ly_in *in, enum ly_stmt *kw, char **word_p, size_t *word_len)
 {
     int prefix;
     const char *word_start;
@@ -642,17 +642,17 @@
     }
 
     /* first skip "optsep", comments */
-    while (**data) {
-        switch (**data) {
+    while (in->current[0]) {
+        switch (in->current[0]) {
         case '/':
-            if ((*data)[1] == '/') {
+            if (in->current[1] == '/') {
                 /* one-line comment */
-                MOVE_INPUT(ctx, data, 2);
-                LY_CHECK_RET(skip_comment(ctx, data, 1));
-            } else if ((*data)[1] == '*') {
+                MOVE_INPUT(ctx, in, 2);
+                LY_CHECK_RET(skip_comment(ctx, in, 1));
+            } else if (in->current[1] == '*') {
                 /* block comment */
-                MOVE_INPUT(ctx, data, 2);
-                LY_CHECK_RET(skip_comment(ctx, data, 2));
+                MOVE_INPUT(ctx, in, 2);
+                LY_CHECK_RET(skip_comment(ctx, in, 2));
             } else {
                 /* error - not a comment after all, keyword cannot start with slash */
                 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '/'.");
@@ -677,12 +677,12 @@
             goto keyword_start;
         }
 
-        ++(*data);
+        ly_in_skip(in, 1);
     }
 
 keyword_start:
-    word_start = *data;
-    *kw = lysp_match_kw(ctx, data);
+    word_start = in->current;
+    *kw = lysp_match_kw(ctx, in);
 
     if (*kw == LY_STMT_SYNTAX_SEMICOLON || *kw == LY_STMT_SYNTAX_LEFT_BRACE || *kw == LY_STMT_SYNTAX_RIGHT_BRACE) {
         goto success;
@@ -690,7 +690,7 @@
 
     if (*kw != LY_STMT_NONE) {
         /* make sure we have the whole keyword */
-        switch (**data) {
+        switch (in->current[0]) {
         case '\n':
         case '\t':
         case ' ':
@@ -701,7 +701,7 @@
              * To avoid repeated check of the prefix syntax, move to the point where the colon was read
              * and we will be checking the keyword (extension instance) itself */
             prefix = 1;
-            MOVE_INPUT(ctx, data, 1);
+            MOVE_INPUT(ctx, in, 1);
             goto extension;
         case '{':
             /* allowed only for input and output statements which can be without arguments */
@@ -710,8 +710,8 @@
             }
             /* fallthrough */
         default:
-            MOVE_INPUT(ctx, data, 1);
-            LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start,
+            MOVE_INPUT(ctx, in, 1);
+            LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, (int)(in->current - word_start), word_start,
                         "a keyword followed by a separator");
             return LY_EVALID;
         }
@@ -719,21 +719,23 @@
         /* still can be an extension */
         prefix = 0;
 extension:
-        while (**data && (**data != ' ') && (**data != '\t') && (**data != '\n') && (**data != '{') && (**data != ';')) {
-            LY_CHECK_ERR_RET(ly_getutf8(data, &c, &len),
-                             LOGVAL_PARSER(ctx, LY_VCODE_INCHAR, (*data)[-len]), LY_EVALID);
+        while (in->current[0] && (in->current[0] != ' ') && (in->current[0] != '\t') && (in->current[0] != '\n')
+                && (in->current[0] != '{') && (in->current[0] != ';')) {
+            LY_CHECK_ERR_RET(ly_getutf8(&in->current, &c, &len),
+                             LOGVAL_PARSER(ctx, LY_VCODE_INCHAR, in->current[-len]), LY_EVALID);
             ++ctx->indent;
             /* check character validity */
-            LY_CHECK_RET(lysp_check_identifierchar((struct lys_parser_ctx *)ctx, c, *data - len == word_start ? 1 : 0, &prefix));
+            LY_CHECK_RET(lysp_check_identifierchar((struct lys_parser_ctx *)ctx, c,
+                                                   in->current - len == word_start ? 1 : 0, &prefix));
         }
-        if (!**data) {
+        if (!in->current[0]) {
             LOGVAL_PARSER(ctx, LY_VCODE_EOF);
             return LY_EVALID;
         }
 
         /* prefix is mandatory for extension instances */
         if (prefix != 2) {
-            LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start, "a keyword");
+            LOGVAL_PARSER(ctx, LY_VCODE_INSTREXP, (int)(in->current - word_start), word_start, "a keyword");
             return LY_EVALID;
         }
 
@@ -742,7 +744,7 @@
 success:
     if (word_p) {
         *word_p = (char *)word_start;
-        *word_len = *data - word_start;
+        *word_len = in->current - word_start;
     }
 
     return LY_SUCCESS;
@@ -752,7 +754,7 @@
  * @brief Parse extension instance substatements.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in] kw Statement keyword value matching @p word value.
  * @param[in] word Extension instance substatement name (keyword).
  * @param[in] word_len Extension instance substatement name length.
@@ -761,7 +763,7 @@
  * @return LY_ERR values.
  */
 static LY_ERR
-parse_ext_substmt(struct lys_yang_parser_ctx *ctx, const char **data, enum ly_stmt kw, char *word, size_t word_len,
+parse_ext_substmt(struct lys_yang_parser_ctx *ctx, struct ly_in *in, enum ly_stmt kw, char *word, size_t word_len,
                   struct lysp_stmt **child)
 {
     char *buf;
@@ -784,7 +786,7 @@
     stmt->kw = kw;
 
     /* get optional argument */
-    LY_CHECK_RET(get_argument(ctx, data, Y_MAYBE_STR_ARG, &stmt->flags, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_MAYBE_STR_ARG, &stmt->flags, &word, &buf, &word_len));
 
     if (word) {
         if (buf) {
@@ -794,8 +796,8 @@
         }
     }
 
-    YANG_READ_SUBSTMT_FOR(ctx, data, child_kw, word, word_len, ret, ) {
-        LY_CHECK_RET(parse_ext_substmt(ctx, data, child_kw, word, word_len, &stmt->child));
+    YANG_READ_SUBSTMT_FOR(ctx, in, child_kw, word, word_len, ret, ) {
+        LY_CHECK_RET(parse_ext_substmt(ctx, in, child_kw, word, word_len, &stmt->child));
     }
     return ret;
 }
@@ -804,7 +806,7 @@
  * @brief Parse extension instance.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in] ext_name Extension instance substatement name (keyword).
  * @param[in] ext_name_len Extension instance substatement name length.
  * @param[in] insubstmt Type of the keyword this extension instance is a substatement of.
@@ -814,7 +816,7 @@
  * @return LY_ERR values.
  */
 static LY_ERR
-parse_ext(struct lys_yang_parser_ctx *ctx, const char **data, const char *ext_name, int ext_name_len, LYEXT_SUBSTMT insubstmt,
+parse_ext(struct lys_yang_parser_ctx *ctx, struct ly_in *in, const char *ext_name, int ext_name_len, LYEXT_SUBSTMT insubstmt,
           LY_ARRAY_COUNT_TYPE insubstmt_index, struct lysp_ext_instance **exts)
 {
     LY_ERR ret = LY_SUCCESS;
@@ -831,14 +833,14 @@
     e->insubstmt_index = insubstmt_index;
 
     /* get optional argument */
-    LY_CHECK_RET(get_argument(ctx, data, Y_MAYBE_STR_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_MAYBE_STR_ARG, NULL, &word, &buf, &word_len));
 
     if (word) {
         INSERT_WORD(ctx, buf, e->argument, word, word_len);
     }
 
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
-        LY_CHECK_RET(parse_ext_substmt(ctx, data, kw, word, word_len, &e->child));
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret,) {
+        LY_CHECK_RET(parse_ext_substmt(ctx, in, kw, word, word_len, &e->child));
     }
     return ret;
 }
@@ -848,7 +850,7 @@
  * description, etc...
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in] substmt Type of this substatement.
  * @param[in] substmt_index Index of this substatement.
  * @param[in,out] value Place to store the parsed value.
@@ -858,7 +860,7 @@
  * @return LY_ERR values.
  */
 static LY_ERR
-parse_text_field(struct lys_yang_parser_ctx *ctx, const char **data, LYEXT_SUBSTMT substmt, uint32_t substmt_index,
+parse_text_field(struct lys_yang_parser_ctx *ctx, struct ly_in *in, LYEXT_SUBSTMT substmt, uint32_t substmt_index,
                  const char **value, enum yang_arg arg, struct lysp_ext_instance **exts)
 {
     LY_ERR ret = LY_SUCCESS;
@@ -872,15 +874,15 @@
     }
 
     /* get value */
-    LY_CHECK_RET(get_argument(ctx, data, arg, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, arg, NULL, &word, &buf, &word_len));
 
     /* store value and spend buf if allocated */
     INSERT_WORD(ctx, buf, *value, word, word_len);
 
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret,) {
         switch (kw) {
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, substmt, substmt_index, exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, substmt, substmt_index, exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
@@ -894,14 +896,14 @@
  * @brief Parse the yang-version statement.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[out] version Storage for the parsed information.
- * @param[in, out] exts Extension instances to add to.
+ * @param[in,out] exts Extension instances to add to.
  *
  * @return LY_ERR values.
  */
 static LY_ERR
-parse_yangversion(struct lys_yang_parser_ctx *ctx, const char **data, uint8_t *version, struct lysp_ext_instance **exts)
+parse_yangversion(struct lys_yang_parser_ctx *ctx, struct ly_in *in, uint8_t *version, struct lysp_ext_instance **exts)
 {
     LY_ERR ret = LY_SUCCESS;
     char *buf, *word;
@@ -914,7 +916,7 @@
     }
 
     /* get value */
-    LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_STR_ARG, NULL, &word, &buf, &word_len));
 
     if ((word_len == 3) && !strncmp(word, "1.0", word_len)) {
         *version = LYS_VERSION_1_0;
@@ -927,10 +929,10 @@
     }
     free(buf);
 
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret,) {
         switch (kw) {
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_VERSION, 0, exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_VERSION, 0, exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yang-version");
@@ -944,7 +946,7 @@
  * @brief Parse the belongs-to statement.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in,out] belongsto Place to store the parsed value.
  * @param[in,out] prefix Place to store the parsed belongs-to prefix value.
  * @param[in,out] exts Extension instances to add to.
@@ -952,7 +954,7 @@
  * @return LY_ERR values.
  */
 static LY_ERR
-parse_belongsto(struct lys_yang_parser_ctx *ctx, const char **data, const char **belongsto, const char **prefix, struct lysp_ext_instance **exts)
+parse_belongsto(struct lys_yang_parser_ctx *ctx, struct ly_in *in, const char **belongsto, const char **prefix, struct lysp_ext_instance **exts)
 {
     LY_ERR ret = LY_SUCCESS;
     char *buf, *word;
@@ -965,17 +967,17 @@
     }
 
     /* get value */
-    LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
 
     INSERT_WORD(ctx, buf, *belongsto, word, word_len);
 
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, goto checks) {
         switch (kw) {
         case LY_STMT_PREFIX:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, prefix, Y_IDENTIF_ARG, exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_PREFIX, 0, prefix, Y_IDENTIF_ARG, exts));
             break;
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_BELONGSTO, 0, exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_BELONGSTO, 0, exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "belongs-to");
@@ -996,14 +998,14 @@
  * @brief Parse the revision-date statement.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in,out] rev Array to store the parsed value in.
  * @param[in,out] exts Extension instances to add to.
  *
  * @return LY_ERR values.
  */
 static LY_ERR
-parse_revisiondate(struct lys_yang_parser_ctx *ctx, const char **data, char *rev, struct lysp_ext_instance **exts)
+parse_revisiondate(struct lys_yang_parser_ctx *ctx, struct ly_in *in, char *rev, struct lysp_ext_instance **exts)
 {
     LY_ERR ret = LY_SUCCESS;
     char *buf, *word;
@@ -1016,7 +1018,7 @@
     }
 
     /* get value */
-    LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_STR_ARG, NULL, &word, &buf, &word_len));
 
     /* check value */
     if (lysp_check_date((struct lys_parser_ctx *)ctx, word, word_len, "revision-date")) {
@@ -1028,10 +1030,10 @@
     strncpy(rev, word, word_len);
     free(buf);
 
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret,) {
         switch (kw) {
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REVISIONDATE, 0, exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_REVISIONDATE, 0, exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision-date");
@@ -1046,13 +1048,13 @@
  *
  * @param[in] ctx yang parser context for logging.
  * @param[in] module_name Name of the module to check name collisions.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in,out] includes Parsed includes to add to.
  *
  * @return LY_ERR values.
  */
 static LY_ERR
-parse_include(struct lys_yang_parser_ctx *ctx, const char *module_name, const char **data, struct lysp_include **includes)
+parse_include(struct lys_yang_parser_ctx *ctx, const char *module_name, struct ly_in *in, struct lysp_include **includes)
 {
     LY_ERR ret = LY_SUCCESS;
     char *buf, *word;
@@ -1063,7 +1065,7 @@
     LY_ARRAY_NEW_RET(ctx->ctx, *includes, inc, LY_EMEM);
 
     /* get value */
-    LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
 
     INSERT_WORD(ctx, buf, inc->name, word, word_len);
 
@@ -1074,21 +1076,21 @@
         return LY_EVALID;
     }
 
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret,) {
         switch (kw) {
         case LY_STMT_DESCRIPTION:
             PARSER_CHECK_STMTVER2_RET(ctx, "description", "include");
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &inc->dsc, Y_STR_ARG, &inc->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &inc->dsc, Y_STR_ARG, &inc->exts));
             break;
         case LY_STMT_REFERENCE:
             PARSER_CHECK_STMTVER2_RET(ctx, "reference", "include");
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &inc->ref, Y_STR_ARG, &inc->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &inc->ref, Y_STR_ARG, &inc->exts));
             break;
         case LY_STMT_REVISION_DATE:
-            LY_CHECK_RET(parse_revisiondate(ctx, data, inc->rev, &inc->exts));
+            LY_CHECK_RET(parse_revisiondate(ctx, in, inc->rev, &inc->exts));
             break;
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inc->exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inc->exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "include");
@@ -1103,13 +1105,13 @@
  *
  * @param[in] ctx yang parser context for logging.
  * @param[in] module_prefix Prefix of the module to check prefix collisions.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in,out] imports Parsed imports to add to.
  *
  * @return LY_ERR values.
  */
 static LY_ERR
-parse_import(struct lys_yang_parser_ctx *ctx, const char *module_prefix, const char **data, struct lysp_import **imports)
+parse_import(struct lys_yang_parser_ctx *ctx, const char *module_prefix, struct ly_in *in, struct lysp_import **imports)
 {
     LY_ERR ret = LY_SUCCESS;
     char *buf, *word;
@@ -1120,28 +1122,28 @@
     LY_ARRAY_NEW_RET(ctx->ctx, *imports, imp, LY_EVALID);
 
     /* get value */
-    LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
     INSERT_WORD(ctx, buf, imp->name, word, word_len);
 
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, goto checks) {
         switch (kw) {
         case LY_STMT_PREFIX:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, &imp->prefix, Y_IDENTIF_ARG, &imp->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_PREFIX, 0, &imp->prefix, Y_IDENTIF_ARG, &imp->exts));
             LY_CHECK_RET(lysp_check_prefix((struct lys_parser_ctx *)ctx, *imports, module_prefix, &imp->prefix), LY_EVALID);
             break;
         case LY_STMT_DESCRIPTION:
             PARSER_CHECK_STMTVER2_RET(ctx, "description", "import");
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &imp->dsc, Y_STR_ARG, &imp->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &imp->dsc, Y_STR_ARG, &imp->exts));
             break;
         case LY_STMT_REFERENCE:
             PARSER_CHECK_STMTVER2_RET(ctx, "reference", "import");
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &imp->ref, Y_STR_ARG, &imp->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &imp->ref, Y_STR_ARG, &imp->exts));
             break;
         case LY_STMT_REVISION_DATE:
-            LY_CHECK_RET(parse_revisiondate(ctx, data, imp->rev, &imp->exts));
+            LY_CHECK_RET(parse_revisiondate(ctx, in, imp->rev, &imp->exts));
             break;
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &imp->exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &imp->exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "import");
@@ -1160,13 +1162,13 @@
  * @brief Parse the revision statement.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in,out] revs Parsed revisions to add to.
  *
  * @return LY_ERR values.
  */
 static LY_ERR
-parse_revision(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_revision **revs)
+parse_revision(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_revision **revs)
 {
     LY_ERR ret = LY_SUCCESS;
     char *buf, *word;
@@ -1177,7 +1179,7 @@
     LY_ARRAY_NEW_RET(ctx->ctx, *revs, rev, LY_EMEM);
 
     /* get value */
-    LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_STR_ARG, NULL, &word, &buf, &word_len));
 
     /* check value */
     if (lysp_check_date((struct lys_parser_ctx *)ctx, word, word_len, "revision")) {
@@ -1188,16 +1190,16 @@
     strncpy(rev->date, word, word_len);
     free(buf);
 
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret,) {
         switch (kw) {
         case LY_STMT_DESCRIPTION:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &rev->dsc, Y_STR_ARG, &rev->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &rev->dsc, Y_STR_ARG, &rev->exts));
             break;
         case LY_STMT_REFERENCE:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &rev->ref, Y_STR_ARG, &rev->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &rev->ref, Y_STR_ARG, &rev->exts));
             break;
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rev->exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rev->exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "revision");
@@ -1211,7 +1213,7 @@
  * @brief Parse a generic text field that can have more instances such as base.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in] substmt Type of this substatement.
  * @param[in,out] texts Parsed values to add to.
  * @param[in] arg Type of the expected argument.
@@ -1220,7 +1222,7 @@
  * @return LY_ERR values.
  */
 static LY_ERR
-parse_text_fields(struct lys_yang_parser_ctx *ctx, const char **data, LYEXT_SUBSTMT substmt, const char ***texts, enum yang_arg arg,
+parse_text_fields(struct lys_yang_parser_ctx *ctx, struct ly_in *in, LYEXT_SUBSTMT substmt, const char ***texts, enum yang_arg arg,
                   struct lysp_ext_instance **exts)
 {
     LY_ERR ret = LY_SUCCESS;
@@ -1233,13 +1235,13 @@
     LY_ARRAY_NEW_RET(ctx->ctx, *texts, item, LY_EMEM);
 
     /* get value */
-    LY_CHECK_RET(get_argument(ctx, data, arg, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, arg, NULL, &word, &buf, &word_len));
 
     INSERT_WORD(ctx, buf, *item, word, word_len);
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret,) {
         switch (kw) {
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, substmt, LY_ARRAY_COUNT(*texts) - 1, exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, substmt, LY_ARRAY_COUNT(*texts) - 1, exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), lyext_substmt2str(substmt));
@@ -1253,14 +1255,14 @@
  * @brief Parse the config statement.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in,out] flags Flags to add to.
  * @param[in,out] exts Extension instances to add to.
  *
  * @return LY_ERR values.
  */
 static LY_ERR
-parse_config(struct lys_yang_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
+parse_config(struct lys_yang_parser_ctx *ctx, struct ly_in *in, uint16_t *flags, struct lysp_ext_instance **exts)
 {
     LY_ERR ret = LY_SUCCESS;
     char *buf, *word;
@@ -1273,7 +1275,7 @@
     }
 
     /* get value */
-    LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_STR_ARG, NULL, &word, &buf, &word_len));
 
     if ((word_len == 4) && !strncmp(word, "true", word_len)) {
         *flags |= LYS_CONFIG_W;
@@ -1286,10 +1288,10 @@
     }
     free(buf);
 
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret,) {
         switch (kw) {
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_CONFIG, 0, exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_CONFIG, 0, exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "config");
@@ -1303,14 +1305,14 @@
  * @brief Parse the mandatory statement.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in,out] flags Flags to add to.
  * @param[in,out] exts Extension instances to add to.
  *
  * @return LY_ERR values.
  */
 static LY_ERR
-parse_mandatory(struct lys_yang_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
+parse_mandatory(struct lys_yang_parser_ctx *ctx, struct ly_in *in, uint16_t *flags, struct lysp_ext_instance **exts)
 {
     LY_ERR ret = LY_SUCCESS;
     char *buf, *word;
@@ -1323,7 +1325,7 @@
     }
 
     /* get value */
-    LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_STR_ARG, NULL, &word, &buf, &word_len));
 
     if ((word_len == 4) && !strncmp(word, "true", word_len)) {
         *flags |= LYS_MAND_TRUE;
@@ -1336,10 +1338,10 @@
     }
     free(buf);
 
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret,) {
         switch (kw) {
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MANDATORY, 0, exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_MANDATORY, 0, exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "mandatory");
@@ -1353,14 +1355,14 @@
  * @brief Parse a restriction such as range or length.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in] restr_kw Type of this particular restriction.
  * @param[in,out] exts Extension instances to add to.
  *
  * @return LY_ERR values.
  */
 static LY_ERR
-parse_restr(struct lys_yang_parser_ctx *ctx, const char **data, enum ly_stmt restr_kw, struct lysp_restr *restr)
+parse_restr(struct lys_yang_parser_ctx *ctx, struct ly_in *in, enum ly_stmt restr_kw, struct lysp_restr *restr)
 {
     LY_ERR ret = LY_SUCCESS;
     char *buf, *word;
@@ -1368,26 +1370,26 @@
     enum ly_stmt kw;
 
     /* get value */
-    LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_STR_ARG, NULL, &word, &buf, &word_len));
 
     CHECK_NONEMPTY(ctx, word_len, ly_stmt2str(restr_kw));
     INSERT_WORD(ctx, buf, restr->arg, word, word_len);
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret,) {
         switch (kw) {
         case LY_STMT_DESCRIPTION:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
             break;
         case LY_STMT_REFERENCE:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &restr->ref, Y_STR_ARG, &restr->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &restr->ref, Y_STR_ARG, &restr->exts));
             break;
         case LY_STMT_ERROR_APP_TAG:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRTAG, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_ERRTAG, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
             break;
         case LY_STMT_ERROR_MESSAGE:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRMSG, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_ERRMSG, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
             break;
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(restr_kw));
@@ -1401,33 +1403,33 @@
  * @brief Parse a restriction that can have more instances such as must.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in] restr_kw Type of this particular restriction.
  * @param[in,out] restrs Restrictions to add to.
  *
  * @return LY_ERR values.
  */
 static LY_ERR
-parse_restrs(struct lys_yang_parser_ctx *ctx, const char **data, enum ly_stmt restr_kw, struct lysp_restr **restrs)
+parse_restrs(struct lys_yang_parser_ctx *ctx, struct ly_in *in, enum ly_stmt restr_kw, struct lysp_restr **restrs)
 {
     struct lysp_restr *restr;
 
     LY_ARRAY_NEW_RET(ctx->ctx, *restrs, restr, LY_EMEM);
-    return parse_restr(ctx, data, restr_kw, restr);
+    return parse_restr(ctx, in, restr_kw, restr);
 }
 
 /**
  * @brief Parse the status statement.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in,out] flags Flags to add to.
  * @param[in,out] exts Extension instances to add to.
  *
  * @return LY_ERR values.
  */
 static LY_ERR
-parse_status(struct lys_yang_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
+parse_status(struct lys_yang_parser_ctx *ctx, struct ly_in *in, uint16_t *flags, struct lysp_ext_instance **exts)
 {
     LY_ERR ret = LY_SUCCESS;
     char *buf, *word;
@@ -1440,7 +1442,7 @@
     }
 
     /* get value */
-    LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_STR_ARG, NULL, &word, &buf, &word_len));
 
     if ((word_len == 7) && !strncmp(word, "current", word_len)) {
         *flags |= LYS_STATUS_CURR;
@@ -1455,10 +1457,10 @@
     }
     free(buf);
 
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret,) {
         switch (kw) {
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_STATUS, 0, exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_STATUS, 0, exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "status");
@@ -1472,13 +1474,13 @@
  * @brief Parse the when statement.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in,out] when_p When pointer to parse to.
  *
  * @return LY_ERR values.
  */
 LY_ERR
-parse_when(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_when **when_p)
+parse_when(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_when **when_p)
 {
     LY_ERR ret = LY_SUCCESS;
     char *buf, *word;
@@ -1495,22 +1497,22 @@
     LY_CHECK_ERR_RET(!when, LOGMEM(ctx->ctx), LY_EMEM);
 
     /* get value */
-    LY_CHECK_ERR_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len), free(when), LY_EMEM);
+    LY_CHECK_ERR_RET(get_argument(ctx, in, Y_STR_ARG, NULL, &word, &buf, &word_len), free(when), LY_EMEM);
     CHECK_NONEMPTY(ctx, word_len, "when");
     INSERT_WORD(ctx, buf, when->cond, word, word_len);
 
     *when_p = when;
 
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret,) {
         switch (kw) {
         case LY_STMT_DESCRIPTION:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &when->dsc, Y_STR_ARG, &when->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &when->dsc, Y_STR_ARG, &when->exts));
             break;
         case LY_STMT_REFERENCE:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &when->ref, Y_STR_ARG, &when->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &when->ref, Y_STR_ARG, &when->exts));
             break;
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &when->exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &when->exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "when");
@@ -1524,14 +1526,14 @@
  * @brief Parse the anydata or anyxml statement.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in] kw Type of this particular keyword.
  * @param[in,out] siblings Siblings to add to.
  *
  * @return LY_ERR values.
  */
 LY_ERR
-parse_any(struct lys_yang_parser_ctx *ctx, const char **data, enum ly_stmt kw, struct lysp_node *parent, struct lysp_node **siblings)
+parse_any(struct lys_yang_parser_ctx *ctx, struct ly_in *in, enum ly_stmt kw, struct lysp_node *parent, struct lysp_node **siblings)
 {
     LY_ERR ret = LY_SUCCESS;
     char *buf, *word;
@@ -1545,38 +1547,38 @@
     any->parent = parent;
 
     /* get name */
-    LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
     INSERT_WORD(ctx, buf, any->name, word, word_len);
 
     /* parse substatements */
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret,) {
         switch (kw) {
         case LY_STMT_CONFIG:
-            LY_CHECK_RET(parse_config(ctx, data, &any->flags, &any->exts));
+            LY_CHECK_RET(parse_config(ctx, in, &any->flags, &any->exts));
             break;
         case LY_STMT_DESCRIPTION:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &any->dsc, Y_STR_ARG, &any->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &any->dsc, Y_STR_ARG, &any->exts));
             break;
         case LY_STMT_IF_FEATURE:
-            LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &any->iffeatures, Y_STR_ARG, &any->exts));
+            LY_CHECK_RET(parse_text_fields(ctx, in, LYEXT_SUBSTMT_IFFEATURE, &any->iffeatures, Y_STR_ARG, &any->exts));
             break;
         case LY_STMT_MANDATORY:
-            LY_CHECK_RET(parse_mandatory(ctx, data, &any->flags, &any->exts));
+            LY_CHECK_RET(parse_mandatory(ctx, in, &any->flags, &any->exts));
             break;
         case LY_STMT_MUST:
-            LY_CHECK_RET(parse_restrs(ctx, data, kw, &any->musts));
+            LY_CHECK_RET(parse_restrs(ctx, in, kw, &any->musts));
             break;
         case LY_STMT_REFERENCE:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &any->ref, Y_STR_ARG, &any->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &any->ref, Y_STR_ARG, &any->exts));
             break;
         case LY_STMT_STATUS:
-            LY_CHECK_RET(parse_status(ctx, data, &any->flags, &any->exts));
+            LY_CHECK_RET(parse_status(ctx, in, &any->flags, &any->exts));
             break;
         case LY_STMT_WHEN:
-            LY_CHECK_RET(parse_when(ctx, data, &any->when));
+            LY_CHECK_RET(parse_when(ctx, in, &any->when));
             break;
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &any->exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &any->exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw),
@@ -1591,7 +1593,7 @@
  * @brief Parse the value or position statement. Substatement of type enum statement.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in] val_kw Type of this particular keyword.
  * @param[in,out] value Value to write to.
  * @param[in,out] flags Flags to write to.
@@ -1600,7 +1602,7 @@
  * @return LY_ERR values.
  */
 LY_ERR
-parse_type_enum_value_pos(struct lys_yang_parser_ctx *ctx, const char **data, enum ly_stmt val_kw, int64_t *value, uint16_t *flags,
+parse_type_enum_value_pos(struct lys_yang_parser_ctx *ctx, struct ly_in *in, enum ly_stmt val_kw, int64_t *value, uint16_t *flags,
                           struct lysp_ext_instance **exts)
 {
     LY_ERR ret = LY_SUCCESS;
@@ -1617,7 +1619,7 @@
     *flags |= LYS_SET_VALUE;
 
     /* get value */
-    LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_STR_ARG, NULL, &word, &buf, &word_len));
 
     if (!word_len || (word[0] == '+') || ((word[0] == '0') && (word_len > 1)) || ((val_kw == LY_STMT_POSITION) && !strncmp(word, "-0", 2))) {
         LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, ly_stmt2str(val_kw));
@@ -1654,10 +1656,10 @@
     }
     free(buf);
 
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret,) {
         switch (kw) {
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, val_kw == LY_STMT_VALUE ? LYEXT_SUBSTMT_VALUE : LYEXT_SUBSTMT_POSITION, 0, exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, val_kw == LY_STMT_VALUE ? LYEXT_SUBSTMT_VALUE : LYEXT_SUBSTMT_POSITION, 0, exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(val_kw));
@@ -1675,14 +1677,14 @@
  * @brief Parse the enum or bit statement. Substatement of type statement.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in] enum_kw Type of this particular keyword.
  * @param[in,out] enums Enums or bits to add to.
  *
  * @return LY_ERR values.
  */
 static LY_ERR
-parse_type_enum(struct lys_yang_parser_ctx *ctx, const char **data, enum ly_stmt enum_kw, struct lysp_type_enum **enums)
+parse_type_enum(struct lys_yang_parser_ctx *ctx, struct ly_in *in, enum ly_stmt enum_kw, struct lysp_type_enum **enums)
 {
     LY_ERR ret = LY_SUCCESS;
     char *buf, *word;
@@ -1693,7 +1695,7 @@
     LY_ARRAY_NEW_RET(ctx->ctx, *enums, enm, LY_EMEM);
 
     /* get value */
-    LY_CHECK_RET(get_argument(ctx, data, enum_kw == LY_STMT_ENUM ? Y_STR_ARG : Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, enum_kw == LY_STMT_ENUM ? Y_STR_ARG : Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
     if (enum_kw == LY_STMT_ENUM) {
         ret = lysp_check_enum_name((struct lys_parser_ctx *)ctx, (const char *)word, word_len);
         LY_CHECK_ERR_RET(ret, free(buf), ret);
@@ -1702,33 +1704,33 @@
     INSERT_WORD(ctx, buf, enm->name, word, word_len);
     CHECK_UNIQUENESS(ctx, *enums, name, ly_stmt2str(enum_kw), enm->name);
 
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret,) {
         switch (kw) {
         case LY_STMT_DESCRIPTION:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &enm->dsc, Y_STR_ARG, &enm->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &enm->dsc, Y_STR_ARG, &enm->exts));
             break;
         case LY_STMT_IF_FEATURE:
             PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", ly_stmt2str(enum_kw));
-            LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &enm->iffeatures, Y_STR_ARG, &enm->exts));
+            LY_CHECK_RET(parse_text_fields(ctx, in, LYEXT_SUBSTMT_IFFEATURE, &enm->iffeatures, Y_STR_ARG, &enm->exts));
             break;
         case LY_STMT_REFERENCE:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &enm->ref, Y_STR_ARG, &enm->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &enm->ref, Y_STR_ARG, &enm->exts));
             break;
         case LY_STMT_STATUS:
-            LY_CHECK_RET(parse_status(ctx, data, &enm->flags, &enm->exts));
+            LY_CHECK_RET(parse_status(ctx, in, &enm->flags, &enm->exts));
             break;
         case LY_STMT_VALUE:
             LY_CHECK_ERR_RET(enum_kw == LY_STMT_BIT, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw),
                              ly_stmt2str(enum_kw)), LY_EVALID);
-            LY_CHECK_RET(parse_type_enum_value_pos(ctx, data, kw, &enm->value, &enm->flags, &enm->exts));
+            LY_CHECK_RET(parse_type_enum_value_pos(ctx, in, kw, &enm->value, &enm->flags, &enm->exts));
             break;
         case LY_STMT_POSITION:
             LY_CHECK_ERR_RET(enum_kw == LY_STMT_ENUM, LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw),
                              ly_stmt2str(enum_kw)), LY_EVALID);
-            LY_CHECK_RET(parse_type_enum_value_pos(ctx, data, kw, &enm->value, &enm->flags, &enm->exts));
+            LY_CHECK_RET(parse_type_enum_value_pos(ctx, in, kw, &enm->value, &enm->flags, &enm->exts));
             break;
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &enm->exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &enm->exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(enum_kw));
@@ -1742,14 +1744,14 @@
  * @brief Parse the fraction-digits statement. Substatement of type statement.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in,out] fracdig Value to write to.
  * @param[in,out] exts Extension instances to add to.
  *
  * @return LY_ERR values.
  */
 static LY_ERR
-parse_type_fracdigits(struct lys_yang_parser_ctx *ctx, const char **data, uint8_t *fracdig, struct lysp_ext_instance **exts)
+parse_type_fracdigits(struct lys_yang_parser_ctx *ctx, struct ly_in *in, uint8_t *fracdig, struct lysp_ext_instance **exts)
 {
     LY_ERR ret = LY_SUCCESS;
     char *buf, *word, *ptr;
@@ -1763,7 +1765,7 @@
     }
 
     /* get value */
-    LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_STR_ARG, NULL, &word, &buf, &word_len));
 
     if (!word_len || (word[0] == '0') || !isdigit(word[0])) {
         LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "fraction-digits");
@@ -1787,10 +1789,10 @@
     *fracdig = num;
     free(buf);
 
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret,) {
         switch (kw) {
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_FRACDIGITS, 0, exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_FRACDIGITS, 0, exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "fraction-digits");
@@ -1804,7 +1806,7 @@
  * @brief Parse the require-instance statement. Substatement of type statement.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in,out] reqinst Value to write to.
  * @param[in,out] flags Flags to write to.
  * @param[in,out] exts Extension instances to add to.
@@ -1812,7 +1814,7 @@
  * @return LY_ERR values.
  */
 static LY_ERR
-parse_type_reqinstance(struct lys_yang_parser_ctx *ctx, const char **data, uint8_t *reqinst, uint16_t *flags,
+parse_type_reqinstance(struct lys_yang_parser_ctx *ctx, struct ly_in *in, uint8_t *reqinst, uint16_t *flags,
                        struct lysp_ext_instance **exts)
 {
     LY_ERR ret = LY_SUCCESS;
@@ -1827,7 +1829,7 @@
     *flags |= LYS_SET_REQINST;
 
     /* get value */
-    LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_STR_ARG, NULL, &word, &buf, &word_len));
 
     if ((word_len == 4) && !strncmp(word, "true", word_len)) {
         *reqinst = 1;
@@ -1838,10 +1840,10 @@
     }
     free(buf);
 
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret,) {
         switch (kw) {
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_REQINSTANCE, 0, exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_REQINSTANCE, 0, exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "require-instance");
@@ -1855,14 +1857,15 @@
  * @brief Parse the modifier statement. Substatement of type pattern statement.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in,out] pat Value to write to.
  * @param[in,out] exts Extension instances to add to.
  *
  * @return LY_ERR values.
  */
 static LY_ERR
-parse_type_pattern_modifier(struct lys_yang_parser_ctx *ctx, const char **data, const char **pat, struct lysp_ext_instance **exts)
+parse_type_pattern_modifier(struct lys_yang_parser_ctx *ctx, struct ly_in *in, const char **pat,
+                            struct lysp_ext_instance **exts)
 {
     LY_ERR ret = LY_SUCCESS;
     char *buf, *word;
@@ -1875,7 +1878,7 @@
     }
 
     /* get value */
-    LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_STR_ARG, NULL, &word, &buf, &word_len));
 
     if ((word_len != 12) || strncmp(word, "invert-match", word_len)) {
         LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "modifier");
@@ -1894,10 +1897,10 @@
     buf[0] = 0x15;
     *pat = lydict_insert_zc(ctx->ctx, buf);
 
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret,) {
         switch (kw) {
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MODIFIER, 0, exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_MODIFIER, 0, exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "modifier");
@@ -1911,13 +1914,13 @@
  * @brief Parse the pattern statement. Substatement of type statement.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in,out] patterns Restrictions to add to.
  *
  * @return LY_ERR values.
  */
 static LY_ERR
-parse_type_pattern(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_restr **patterns)
+parse_type_pattern(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_restr **patterns)
 {
     LY_ERR ret = LY_SUCCESS;
     char *buf, *word;
@@ -1928,7 +1931,7 @@
     LY_ARRAY_NEW_RET(ctx->ctx, *patterns, restr, LY_EMEM);
 
     /* get value */
-    LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_STR_ARG, NULL, &word, &buf, &word_len));
 
     /* add special meaning first byte */
     if (buf) {
@@ -1943,26 +1946,26 @@
     buf[word_len + 1] = '\0'; /* terminating NULL byte */
     restr->arg = lydict_insert_zc(ctx->ctx, buf);
 
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret,) {
         switch (kw) {
         case LY_STMT_DESCRIPTION:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &restr->dsc, Y_STR_ARG, &restr->exts));
             break;
         case LY_STMT_REFERENCE:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &restr->ref, Y_STR_ARG, &restr->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &restr->ref, Y_STR_ARG, &restr->exts));
             break;
         case LY_STMT_ERROR_APP_TAG:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRTAG, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_ERRTAG, 0, &restr->eapptag, Y_STR_ARG, &restr->exts));
             break;
         case LY_STMT_ERROR_MESSAGE:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_ERRMSG, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_ERRMSG, 0, &restr->emsg, Y_STR_ARG, &restr->exts));
             break;
         case LY_STMT_MODIFIER:
             PARSER_CHECK_STMTVER2_RET(ctx, "modifier", "pattern");
-            LY_CHECK_RET(parse_type_pattern_modifier(ctx, data, &restr->arg, &restr->exts));
+            LY_CHECK_RET(parse_type_pattern_modifier(ctx, in, &restr->arg, &restr->exts));
             break;
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &restr->exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "pattern");
@@ -1976,13 +1979,13 @@
  * @brief Parse the type statement.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in,out] type Type to wrote to.
  *
  * @return LY_ERR values.
  */
 static LY_ERR
-parse_type(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_type *type)
+parse_type(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_type *type)
 {
     LY_ERR ret = LY_SUCCESS;
     char *buf, *word;
@@ -1997,25 +2000,25 @@
     }
 
     /* get value */
-    LY_CHECK_RET(get_argument(ctx, data, Y_PREF_IDENTIF_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_PREF_IDENTIF_ARG, NULL, &word, &buf, &word_len));
     INSERT_WORD(ctx, buf, type->name, word, word_len);
 
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret,) {
         switch (kw) {
         case LY_STMT_BASE:
-            LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_BASE, &type->bases, Y_PREF_IDENTIF_ARG, &type->exts));
+            LY_CHECK_RET(parse_text_fields(ctx, in, LYEXT_SUBSTMT_BASE, &type->bases, Y_PREF_IDENTIF_ARG, &type->exts));
             type->flags |= LYS_SET_BASE;
             break;
         case LY_STMT_BIT:
-            LY_CHECK_RET(parse_type_enum(ctx, data, kw, &type->bits));
+            LY_CHECK_RET(parse_type_enum(ctx, in, kw, &type->bits));
             type->flags |= LYS_SET_BIT;
             break;
         case LY_STMT_ENUM:
-            LY_CHECK_RET(parse_type_enum(ctx, data, kw, &type->enums));
+            LY_CHECK_RET(parse_type_enum(ctx, in, kw, &type->enums));
             type->flags |= LYS_SET_ENUM;
             break;
         case LY_STMT_FRACTION_DIGITS:
-            LY_CHECK_RET(parse_type_fracdigits(ctx, data, &type->fraction_digits, &type->exts));
+            LY_CHECK_RET(parse_type_fracdigits(ctx, in, &type->fraction_digits, &type->exts));
             type->flags |= LYS_SET_FRDIGITS;
             break;
         case LY_STMT_LENGTH:
@@ -2026,7 +2029,7 @@
             type->length = calloc(1, sizeof *type->length);
             LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->ctx), LY_EMEM);
 
-            LY_CHECK_RET(parse_restr(ctx, data, kw, type->length));
+            LY_CHECK_RET(parse_restr(ctx, in, kw, type->length));
             type->flags |= LYS_SET_LENGTH;
             break;
         case LY_STMT_PATH:
@@ -2035,7 +2038,7 @@
                 return LY_EVALID;
             }
 
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_PATH, 0, &str_path, Y_STR_ARG, &type->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_PATH, 0, &str_path, Y_STR_ARG, &type->exts));
             ret = ly_path_parse(ctx->ctx, str_path, 0, LY_PATH_BEGIN_EITHER, LY_PATH_LREF_TRUE,
                                 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &type->path);
             lydict_remove(ctx->ctx, str_path);
@@ -2043,7 +2046,7 @@
             type->flags |= LYS_SET_PATH;
             break;
         case LY_STMT_PATTERN:
-            LY_CHECK_RET(parse_type_pattern(ctx, data, &type->patterns));
+            LY_CHECK_RET(parse_type_pattern(ctx, in, &type->patterns));
             type->flags |= LYS_SET_PATTERN;
             break;
         case LY_STMT_RANGE:
@@ -2054,20 +2057,20 @@
             type->range = calloc(1, sizeof *type->range);
             LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->ctx), LY_EMEM);
 
-            LY_CHECK_RET(parse_restr(ctx, data, kw, type->range));
+            LY_CHECK_RET(parse_restr(ctx, in, kw, type->range));
             type->flags |= LYS_SET_RANGE;
             break;
         case LY_STMT_REQUIRE_INSTANCE:
-            LY_CHECK_RET(parse_type_reqinstance(ctx, data, &type->require_instance, &type->flags, &type->exts));
+            LY_CHECK_RET(parse_type_reqinstance(ctx, in, &type->require_instance, &type->flags, &type->exts));
             /* LYS_SET_REQINST checked and set inside parse_type_reqinstance() */
             break;
         case LY_STMT_TYPE:
             LY_ARRAY_NEW_RET(ctx->ctx, type->types, nest_type, LY_EMEM);
-            LY_CHECK_RET(parse_type(ctx, data, nest_type));
+            LY_CHECK_RET(parse_type(ctx, in, nest_type));
             type->flags |= LYS_SET_TYPE;
             break;
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &type->exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &type->exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "type");
@@ -2081,13 +2084,13 @@
  * @brief Parse the leaf statement.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in,out] siblings Siblings to add to.
  *
  * @return LY_ERR values.
  */
 LY_ERR
-parse_leaf(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
+parse_leaf(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_node *parent, struct lysp_node **siblings)
 {
     LY_ERR ret = LY_SUCCESS;
     char *buf, *word;
@@ -2101,47 +2104,47 @@
     leaf->parent = parent;
 
     /* get name */
-    LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
     INSERT_WORD(ctx, buf, leaf->name, word, word_len);
 
     /* parse substatements */
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, goto checks) {
         switch (kw) {
         case LY_STMT_CONFIG:
-            LY_CHECK_RET(parse_config(ctx, data, &leaf->flags, &leaf->exts));
+            LY_CHECK_RET(parse_config(ctx, in, &leaf->flags, &leaf->exts));
             break;
         case LY_STMT_DEFAULT:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &leaf->dflt, Y_STR_ARG, &leaf->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DEFAULT, 0, &leaf->dflt, Y_STR_ARG, &leaf->exts));
             break;
         case LY_STMT_DESCRIPTION:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &leaf->dsc, Y_STR_ARG, &leaf->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &leaf->dsc, Y_STR_ARG, &leaf->exts));
             break;
         case LY_STMT_IF_FEATURE:
-            LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &leaf->iffeatures, Y_STR_ARG, &leaf->exts));
+            LY_CHECK_RET(parse_text_fields(ctx, in, LYEXT_SUBSTMT_IFFEATURE, &leaf->iffeatures, Y_STR_ARG, &leaf->exts));
             break;
         case LY_STMT_MANDATORY:
-            LY_CHECK_RET(parse_mandatory(ctx, data, &leaf->flags, &leaf->exts));
+            LY_CHECK_RET(parse_mandatory(ctx, in, &leaf->flags, &leaf->exts));
             break;
         case LY_STMT_MUST:
-            LY_CHECK_RET(parse_restrs(ctx, data, kw, &leaf->musts));
+            LY_CHECK_RET(parse_restrs(ctx, in, kw, &leaf->musts));
             break;
         case LY_STMT_REFERENCE:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &leaf->ref, Y_STR_ARG, &leaf->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &leaf->ref, Y_STR_ARG, &leaf->exts));
             break;
         case LY_STMT_STATUS:
-            LY_CHECK_RET(parse_status(ctx, data, &leaf->flags, &leaf->exts));
+            LY_CHECK_RET(parse_status(ctx, in, &leaf->flags, &leaf->exts));
             break;
         case LY_STMT_TYPE:
-            LY_CHECK_RET(parse_type(ctx, data, &leaf->type));
+            LY_CHECK_RET(parse_type(ctx, in, &leaf->type));
             break;
         case LY_STMT_UNITS:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, &leaf->units, Y_STR_ARG, &leaf->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_UNITS, 0, &leaf->units, Y_STR_ARG, &leaf->exts));
             break;
         case LY_STMT_WHEN:
-            LY_CHECK_RET(parse_when(ctx, data, &leaf->when));
+            LY_CHECK_RET(parse_when(ctx, in, &leaf->when));
             break;
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &leaf->exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &leaf->exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "leaf");
@@ -2167,7 +2170,7 @@
  * @brief Parse the max-elements statement.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in,out] max Value to write to.
  * @param[in,out] flags Flags to write to.
  * @param[in,out] exts Extension instances to add to.
@@ -2175,7 +2178,8 @@
  * @return LY_ERR values.
  */
 LY_ERR
-parse_maxelements(struct lys_yang_parser_ctx *ctx, const char **data, uint32_t *max, uint16_t *flags, struct lysp_ext_instance **exts)
+parse_maxelements(struct lys_yang_parser_ctx *ctx, struct ly_in *in, uint32_t *max, uint16_t *flags,
+                  struct lysp_ext_instance **exts)
 {
     LY_ERR ret = LY_SUCCESS;
     char *buf, *word, *ptr;
@@ -2190,7 +2194,7 @@
     *flags |= LYS_SET_MAX;
 
     /* get value */
-    LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_STR_ARG, NULL, &word, &buf, &word_len));
 
     if (!word_len || (word[0] == '0') || ((word[0] != 'u') && !isdigit(word[0]))) {
         LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "max-elements");
@@ -2217,10 +2221,10 @@
     }
     free(buf);
 
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret,) {
         switch (kw) {
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MAX, 0, exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_MAX, 0, exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "max-elements");
@@ -2234,7 +2238,7 @@
  * @brief Parse the min-elements statement.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in,out] min Value to write to.
  * @param[in,out] flags Flags to write to.
  * @param[in,out] exts Extension instances to add to.
@@ -2242,7 +2246,8 @@
  * @return LY_ERR values.
  */
 LY_ERR
-parse_minelements(struct lys_yang_parser_ctx *ctx, const char **data, uint32_t *min, uint16_t *flags, struct lysp_ext_instance **exts)
+parse_minelements(struct lys_yang_parser_ctx *ctx, struct ly_in *in, uint32_t *min, uint16_t *flags,
+                  struct lysp_ext_instance **exts)
 {
     LY_ERR ret = LY_SUCCESS;
     char *buf, *word, *ptr;
@@ -2257,7 +2262,7 @@
     *flags |= LYS_SET_MIN;
 
     /* get value */
-    LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_STR_ARG, NULL, &word, &buf, &word_len));
 
     if (!word_len || !isdigit(word[0]) || ((word[0] == '0') && (word_len > 1))) {
         LOGVAL_PARSER(ctx, LY_VCODE_INVAL, word_len, word, "min-elements");
@@ -2281,10 +2286,10 @@
     *min = num;
     free(buf);
 
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret,) {
         switch (kw) {
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_MIN, 0, exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_MIN, 0, exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "min-elements");
@@ -2298,14 +2303,14 @@
  * @brief Parse the ordered-by statement.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in,out] flags Flags to write to.
  * @param[in,out] exts Extension instances to add to.
  *
  * @return LY_ERR values.
  */
 static LY_ERR
-parse_orderedby(struct lys_yang_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
+parse_orderedby(struct lys_yang_parser_ctx *ctx, struct ly_in *in, uint16_t *flags, struct lysp_ext_instance **exts)
 {
     LY_ERR ret = LY_SUCCESS;
     char *buf, *word;
@@ -2318,7 +2323,7 @@
     }
 
     /* get value */
-    LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_STR_ARG, NULL, &word, &buf, &word_len));
 
     if ((word_len == 6) && !strncmp(word, "system", word_len)) {
         *flags |= LYS_ORDBY_SYSTEM;
@@ -2331,10 +2336,10 @@
     }
     free(buf);
 
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret,) {
         switch (kw) {
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ORDEREDBY, 0, exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_ORDEREDBY, 0, exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "ordered-by");
@@ -2348,13 +2353,13 @@
  * @brief Parse the leaf-list statement.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in,out] siblings Siblings to add to.
  *
  * @return LY_ERR values.
  */
 LY_ERR
-parse_leaflist(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
+parse_leaflist(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_node *parent, struct lysp_node **siblings)
 {
     LY_ERR ret = LY_SUCCESS;
     char *buf, *word;
@@ -2368,54 +2373,54 @@
     llist->parent = parent;
 
     /* get name */
-    LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
     INSERT_WORD(ctx, buf, llist->name, word, word_len);
 
     /* parse substatements */
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, goto checks) {
         switch (kw) {
         case LY_STMT_CONFIG:
-            LY_CHECK_RET(parse_config(ctx, data, &llist->flags, &llist->exts));
+            LY_CHECK_RET(parse_config(ctx, in, &llist->flags, &llist->exts));
             break;
         case LY_STMT_DEFAULT:
             PARSER_CHECK_STMTVER2_RET(ctx, "default", "leaf-list");
-            LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_DEFAULT, &llist->dflts, Y_STR_ARG, &llist->exts));
+            LY_CHECK_RET(parse_text_fields(ctx, in, LYEXT_SUBSTMT_DEFAULT, &llist->dflts, Y_STR_ARG, &llist->exts));
             break;
         case LY_STMT_DESCRIPTION:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &llist->dsc, Y_STR_ARG, &llist->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &llist->dsc, Y_STR_ARG, &llist->exts));
             break;
         case LY_STMT_IF_FEATURE:
-            LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &llist->iffeatures, Y_STR_ARG, &llist->exts));
+            LY_CHECK_RET(parse_text_fields(ctx, in, LYEXT_SUBSTMT_IFFEATURE, &llist->iffeatures, Y_STR_ARG, &llist->exts));
             break;
         case LY_STMT_MAX_ELEMENTS:
-            LY_CHECK_RET(parse_maxelements(ctx, data, &llist->max, &llist->flags, &llist->exts));
+            LY_CHECK_RET(parse_maxelements(ctx, in, &llist->max, &llist->flags, &llist->exts));
             break;
         case LY_STMT_MIN_ELEMENTS:
-            LY_CHECK_RET(parse_minelements(ctx, data, &llist->min, &llist->flags, &llist->exts));
+            LY_CHECK_RET(parse_minelements(ctx, in, &llist->min, &llist->flags, &llist->exts));
             break;
         case LY_STMT_MUST:
-            LY_CHECK_RET(parse_restrs(ctx, data, kw, &llist->musts));
+            LY_CHECK_RET(parse_restrs(ctx, in, kw, &llist->musts));
             break;
         case LY_STMT_ORDERED_BY:
-            LY_CHECK_RET(parse_orderedby(ctx, data, &llist->flags, &llist->exts));
+            LY_CHECK_RET(parse_orderedby(ctx, in, &llist->flags, &llist->exts));
             break;
         case LY_STMT_REFERENCE:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &llist->ref, Y_STR_ARG, &llist->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &llist->ref, Y_STR_ARG, &llist->exts));
             break;
         case LY_STMT_STATUS:
-            LY_CHECK_RET(parse_status(ctx, data, &llist->flags, &llist->exts));
+            LY_CHECK_RET(parse_status(ctx, in, &llist->flags, &llist->exts));
             break;
         case LY_STMT_TYPE:
-            LY_CHECK_RET(parse_type(ctx, data, &llist->type));
+            LY_CHECK_RET(parse_type(ctx, in, &llist->type));
             break;
         case LY_STMT_UNITS:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, &llist->units, Y_STR_ARG, &llist->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_UNITS, 0, &llist->units, Y_STR_ARG, &llist->exts));
             break;
         case LY_STMT_WHEN:
-            LY_CHECK_RET(parse_when(ctx, data, &llist->when));
+            LY_CHECK_RET(parse_when(ctx, in, &llist->when));
             break;
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &llist->exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &llist->exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "llist");
@@ -2447,13 +2452,13 @@
  * @brief Parse the refine statement.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in,out] refines Refines to add to.
  *
  * @return LY_ERR values.
  */
 static LY_ERR
-parse_refine(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_refine **refines)
+parse_refine(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_refine **refines)
 {
     LY_ERR ret = LY_SUCCESS;
     char *buf, *word;
@@ -2464,45 +2469,45 @@
     LY_ARRAY_NEW_RET(ctx->ctx, *refines, rf, LY_EMEM);
 
     /* get value */
-    LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_STR_ARG, NULL, &word, &buf, &word_len));
     CHECK_NONEMPTY(ctx, word_len, "refine");
     INSERT_WORD(ctx, buf, rf->nodeid, word, word_len);
 
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret,) {
         switch (kw) {
         case LY_STMT_CONFIG:
-            LY_CHECK_RET(parse_config(ctx, data, &rf->flags, &rf->exts));
+            LY_CHECK_RET(parse_config(ctx, in, &rf->flags, &rf->exts));
             break;
         case LY_STMT_DEFAULT:
-            LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_DEFAULT, &rf->dflts, Y_STR_ARG, &rf->exts));
+            LY_CHECK_RET(parse_text_fields(ctx, in, LYEXT_SUBSTMT_DEFAULT, &rf->dflts, Y_STR_ARG, &rf->exts));
             break;
         case LY_STMT_DESCRIPTION:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &rf->dsc, Y_STR_ARG, &rf->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &rf->dsc, Y_STR_ARG, &rf->exts));
             break;
         case LY_STMT_IF_FEATURE:
             PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", "refine");
-            LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &rf->iffeatures, Y_STR_ARG, &rf->exts));
+            LY_CHECK_RET(parse_text_fields(ctx, in, LYEXT_SUBSTMT_IFFEATURE, &rf->iffeatures, Y_STR_ARG, &rf->exts));
             break;
         case LY_STMT_MAX_ELEMENTS:
-            LY_CHECK_RET(parse_maxelements(ctx, data, &rf->max, &rf->flags, &rf->exts));
+            LY_CHECK_RET(parse_maxelements(ctx, in, &rf->max, &rf->flags, &rf->exts));
             break;
         case LY_STMT_MIN_ELEMENTS:
-            LY_CHECK_RET(parse_minelements(ctx, data, &rf->min, &rf->flags, &rf->exts));
+            LY_CHECK_RET(parse_minelements(ctx, in, &rf->min, &rf->flags, &rf->exts));
             break;
         case LY_STMT_MUST:
-            LY_CHECK_RET(parse_restrs(ctx, data, kw, &rf->musts));
+            LY_CHECK_RET(parse_restrs(ctx, in, kw, &rf->musts));
             break;
         case LY_STMT_MANDATORY:
-            LY_CHECK_RET(parse_mandatory(ctx, data, &rf->flags, &rf->exts));
+            LY_CHECK_RET(parse_mandatory(ctx, in, &rf->flags, &rf->exts));
             break;
         case LY_STMT_REFERENCE:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &rf->ref, Y_STR_ARG, &rf->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &rf->ref, Y_STR_ARG, &rf->exts));
             break;
         case LY_STMT_PRESENCE:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_PRESENCE, 0, &rf->presence, Y_STR_ARG, &rf->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_PRESENCE, 0, &rf->presence, Y_STR_ARG, &rf->exts));
             break;
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rf->exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &rf->exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "refine");
@@ -2516,13 +2521,13 @@
  * @brief Parse the typedef statement.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in,out] typedefs Typedefs to add to.
  *
  * @return LY_ERR values.
  */
 static LY_ERR
-parse_typedef(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, const char **data, struct lysp_tpdf **typedefs)
+parse_typedef(struct lys_yang_parser_ctx *ctx, struct lysp_node *parent, struct ly_in *in, struct lysp_tpdf **typedefs)
 {
     LY_ERR ret = LY_SUCCESS;
     char *buf, *word;
@@ -2533,32 +2538,32 @@
     LY_ARRAY_NEW_RET(ctx->ctx, *typedefs, tpdf, LY_EMEM);
 
     /* get value */
-    LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
     INSERT_WORD(ctx, buf, tpdf->name, word, word_len);
 
     /* parse substatements */
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, goto checks) {
         switch (kw) {
         case LY_STMT_DEFAULT:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &tpdf->dflt, Y_STR_ARG, &tpdf->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DEFAULT, 0, &tpdf->dflt, Y_STR_ARG, &tpdf->exts));
             break;
         case LY_STMT_DESCRIPTION:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &tpdf->dsc, Y_STR_ARG, &tpdf->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &tpdf->dsc, Y_STR_ARG, &tpdf->exts));
             break;
         case LY_STMT_REFERENCE:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &tpdf->ref, Y_STR_ARG, &tpdf->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &tpdf->ref, Y_STR_ARG, &tpdf->exts));
             break;
         case LY_STMT_STATUS:
-            LY_CHECK_RET(parse_status(ctx, data, &tpdf->flags, &tpdf->exts));
+            LY_CHECK_RET(parse_status(ctx, in, &tpdf->flags, &tpdf->exts));
             break;
         case LY_STMT_TYPE:
-            LY_CHECK_RET(parse_type(ctx, data, &tpdf->type));
+            LY_CHECK_RET(parse_type(ctx, in, &tpdf->type));
             break;
         case LY_STMT_UNITS:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, &tpdf->units, Y_STR_ARG, &tpdf->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_UNITS, 0, &tpdf->units, Y_STR_ARG, &tpdf->exts));
             break;
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &tpdf->exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &tpdf->exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "typedef");
@@ -2585,14 +2590,14 @@
  * @brief Parse the input or output statement.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in] kw Type of this particular keyword
  * @param[in,out] inout_p Input/output pointer to write to.
  *
  * @return LY_ERR values.
  */
 static LY_ERR
-parse_inout(struct lys_yang_parser_ctx *ctx, const char **data, enum ly_stmt inout_kw, struct lysp_node *parent, struct lysp_action_inout *inout_p)
+parse_inout(struct lys_yang_parser_ctx *ctx, struct ly_in *in, enum ly_stmt inout_kw, struct lysp_node *parent, struct lysp_action_inout *inout_p)
 {
     LY_ERR ret = LY_SUCCESS;
     char *word;
@@ -2609,44 +2614,44 @@
     inout_p->parent = parent;
 
     /* parse substatements */
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, goto checks) {
         switch (kw) {
         case LY_STMT_ANYDATA:
             PARSER_CHECK_STMTVER2_RET(ctx, "anydata", ly_stmt2str(inout_kw));
             /* fall through */
         case LY_STMT_ANYXML:
-            LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)inout_p, &inout_p->data));
+            LY_CHECK_RET(parse_any(ctx, in, kw, (struct lysp_node*)inout_p, &inout_p->data));
             break;
         case LY_STMT_CHOICE:
-            LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
+            LY_CHECK_RET(parse_choice(ctx, in, (struct lysp_node*)inout_p, &inout_p->data));
             break;
         case LY_STMT_CONTAINER:
-            LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
+            LY_CHECK_RET(parse_container(ctx, in, (struct lysp_node*)inout_p, &inout_p->data));
             break;
         case LY_STMT_LEAF:
-            LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
+            LY_CHECK_RET(parse_leaf(ctx, in, (struct lysp_node*)inout_p, &inout_p->data));
             break;
         case LY_STMT_LEAF_LIST:
-            LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
+            LY_CHECK_RET(parse_leaflist(ctx, in, (struct lysp_node*)inout_p, &inout_p->data));
             break;
         case LY_STMT_LIST:
-            LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
+            LY_CHECK_RET(parse_list(ctx, in, (struct lysp_node*)inout_p, &inout_p->data));
             break;
         case LY_STMT_USES:
-            LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)inout_p, &inout_p->data));
+            LY_CHECK_RET(parse_uses(ctx, in, (struct lysp_node*)inout_p, &inout_p->data));
             break;
         case LY_STMT_TYPEDEF:
-            LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)inout_p, data, &inout_p->typedefs));
+            LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)inout_p, in, &inout_p->typedefs));
             break;
         case LY_STMT_MUST:
             PARSER_CHECK_STMTVER2_RET(ctx, "must", ly_stmt2str(inout_kw));
-            LY_CHECK_RET(parse_restrs(ctx, data, kw, &inout_p->musts));
+            LY_CHECK_RET(parse_restrs(ctx, in, kw, &inout_p->musts));
             break;
         case LY_STMT_GROUPING:
-            LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)inout_p, &inout_p->groupings));
+            LY_CHECK_RET(parse_grouping(ctx, in, (struct lysp_node*)inout_p, &inout_p->groupings));
             break;
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inout_p->exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &inout_p->exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), ly_stmt2str(inout_kw));
@@ -2671,13 +2676,13 @@
  * @brief Parse the action statement.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in,out] actions Actions to add to.
  *
  * @return LY_ERR values.
  */
 LY_ERR
-parse_action(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_action **actions)
+parse_action(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_node *parent, struct lysp_action **actions)
 {
     LY_ERR ret = LY_SUCCESS;
     char *buf, *word;
@@ -2688,41 +2693,41 @@
     LY_ARRAY_NEW_RET(ctx->ctx, *actions, act, LY_EMEM);
 
     /* get value */
-    LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
     INSERT_WORD(ctx, buf, act->name, word, word_len);
     act->nodetype = parent ? LYS_ACTION : LYS_RPC;
     act->parent = parent;
 
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, goto checks) {
         switch (kw) {
         case LY_STMT_DESCRIPTION:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &act->dsc, Y_STR_ARG, &act->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &act->dsc, Y_STR_ARG, &act->exts));
             break;
         case LY_STMT_IF_FEATURE:
-            LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &act->iffeatures, Y_STR_ARG, &act->exts));
+            LY_CHECK_RET(parse_text_fields(ctx, in, LYEXT_SUBSTMT_IFFEATURE, &act->iffeatures, Y_STR_ARG, &act->exts));
             break;
         case LY_STMT_REFERENCE:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &act->ref, Y_STR_ARG, &act->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &act->ref, Y_STR_ARG, &act->exts));
             break;
         case LY_STMT_STATUS:
-            LY_CHECK_RET(parse_status(ctx, data, &act->flags, &act->exts));
+            LY_CHECK_RET(parse_status(ctx, in, &act->flags, &act->exts));
             break;
 
         case LY_STMT_INPUT:
-            LY_CHECK_RET(parse_inout(ctx, data, kw, (struct lysp_node*)act, &act->input));
+            LY_CHECK_RET(parse_inout(ctx, in, kw, (struct lysp_node*)act, &act->input));
             break;
         case LY_STMT_OUTPUT:
-            LY_CHECK_RET(parse_inout(ctx, data, kw, (struct lysp_node*)act, &act->output));
+            LY_CHECK_RET(parse_inout(ctx, in, kw, (struct lysp_node*)act, &act->output));
             break;
 
         case LY_STMT_TYPEDEF:
-            LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)act, data, &act->typedefs));
+            LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)act, in, &act->typedefs));
             break;
         case LY_STMT_GROUPING:
-            LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)act, &act->groupings));
+            LY_CHECK_RET(parse_grouping(ctx, in, (struct lysp_node*)act, &act->groupings));
             break;
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &act->exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &act->exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), parent ? "action" : "rpc");
@@ -2741,13 +2746,13 @@
  * @brief Parse the notification statement.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in,out] notifs Notifications to add to.
  *
  * @return LY_ERR values.
  */
 LY_ERR
-parse_notif(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_notif **notifs)
+parse_notif(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_node *parent, struct lysp_notif **notifs)
 {
     LY_ERR ret = LY_SUCCESS;
     char *buf, *word;
@@ -2758,63 +2763,63 @@
     LY_ARRAY_NEW_RET(ctx->ctx, *notifs, notif, LY_EMEM);
 
     /* get value */
-    LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
     INSERT_WORD(ctx, buf, notif->name, word, word_len);
     notif->nodetype = LYS_NOTIF;
     notif->parent = parent;
 
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, goto checks) {
         switch (kw) {
         case LY_STMT_DESCRIPTION:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &notif->dsc, Y_STR_ARG, &notif->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &notif->dsc, Y_STR_ARG, &notif->exts));
             break;
         case LY_STMT_IF_FEATURE:
-            LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &notif->iffeatures, Y_STR_ARG, &notif->exts));
+            LY_CHECK_RET(parse_text_fields(ctx, in, LYEXT_SUBSTMT_IFFEATURE, &notif->iffeatures, Y_STR_ARG, &notif->exts));
             break;
         case LY_STMT_REFERENCE:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &notif->ref, Y_STR_ARG, &notif->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &notif->ref, Y_STR_ARG, &notif->exts));
             break;
         case LY_STMT_STATUS:
-            LY_CHECK_RET(parse_status(ctx, data, &notif->flags, &notif->exts));
+            LY_CHECK_RET(parse_status(ctx, in, &notif->flags, &notif->exts));
             break;
 
         case LY_STMT_ANYDATA:
             PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "notification");
             /* fall through */
         case LY_STMT_ANYXML:
-            LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)notif, &notif->data));
+            LY_CHECK_RET(parse_any(ctx, in, kw, (struct lysp_node*)notif, &notif->data));
             break;
         case LY_STMT_CHOICE:
-            LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)notif, &notif->data));
+            LY_CHECK_RET(parse_case(ctx, in, (struct lysp_node*)notif, &notif->data));
             break;
         case LY_STMT_CONTAINER:
-            LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)notif, &notif->data));
+            LY_CHECK_RET(parse_container(ctx, in, (struct lysp_node*)notif, &notif->data));
             break;
         case LY_STMT_LEAF:
-            LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)notif, &notif->data));
+            LY_CHECK_RET(parse_leaf(ctx, in, (struct lysp_node*)notif, &notif->data));
             break;
         case LY_STMT_LEAF_LIST:
-            LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)notif, &notif->data));
+            LY_CHECK_RET(parse_leaflist(ctx, in, (struct lysp_node*)notif, &notif->data));
             break;
         case LY_STMT_LIST:
-            LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)notif, &notif->data));
+            LY_CHECK_RET(parse_list(ctx, in, (struct lysp_node*)notif, &notif->data));
             break;
         case LY_STMT_USES:
-            LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)notif, &notif->data));
+            LY_CHECK_RET(parse_uses(ctx, in, (struct lysp_node*)notif, &notif->data));
             break;
 
         case LY_STMT_MUST:
             PARSER_CHECK_STMTVER2_RET(ctx, "must", "notification");
-            LY_CHECK_RET(parse_restrs(ctx, data, kw, &notif->musts));
+            LY_CHECK_RET(parse_restrs(ctx, in, kw, &notif->musts));
             break;
         case LY_STMT_TYPEDEF:
-            LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)notif, data, &notif->typedefs));
+            LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)notif, in, &notif->typedefs));
             break;
         case LY_STMT_GROUPING:
-            LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)notif, &notif->groupings));
+            LY_CHECK_RET(parse_grouping(ctx, in, (struct lysp_node*)notif, &notif->groupings));
             break;
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &notif->exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &notif->exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "notification");
@@ -2833,13 +2838,13 @@
  * @brief Parse the grouping statement.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in,out] groupings Groupings to add to.
  *
  * @return LY_ERR values.
  */
 LY_ERR
-parse_grouping(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_grp **groupings)
+parse_grouping(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_node *parent, struct lysp_grp **groupings)
 {
     LY_ERR ret = LY_SUCCESS;
     char *buf, *word;
@@ -2850,64 +2855,64 @@
     LY_ARRAY_NEW_RET(ctx->ctx, *groupings, grp, LY_EMEM);
 
     /* get value */
-    LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
     INSERT_WORD(ctx, buf, grp->name, word, word_len);
     grp->nodetype = LYS_GROUPING;
     grp->parent = parent;
 
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, goto checks) {
         switch (kw) {
         case LY_STMT_DESCRIPTION:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &grp->dsc, Y_STR_ARG, &grp->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &grp->dsc, Y_STR_ARG, &grp->exts));
             break;
         case LY_STMT_REFERENCE:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &grp->ref, Y_STR_ARG, &grp->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &grp->ref, Y_STR_ARG, &grp->exts));
             break;
         case LY_STMT_STATUS:
-            LY_CHECK_RET(parse_status(ctx, data, &grp->flags, &grp->exts));
+            LY_CHECK_RET(parse_status(ctx, in, &grp->flags, &grp->exts));
             break;
 
         case LY_STMT_ANYDATA:
             PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "grouping");
             /* fall through */
         case LY_STMT_ANYXML:
-            LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)grp, &grp->data));
+            LY_CHECK_RET(parse_any(ctx, in, kw, (struct lysp_node*)grp, &grp->data));
             break;
         case LY_STMT_CHOICE:
-            LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)grp, &grp->data));
+            LY_CHECK_RET(parse_choice(ctx, in, (struct lysp_node*)grp, &grp->data));
             break;
         case LY_STMT_CONTAINER:
-            LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)grp, &grp->data));
+            LY_CHECK_RET(parse_container(ctx, in, (struct lysp_node*)grp, &grp->data));
             break;
         case LY_STMT_LEAF:
-            LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)grp, &grp->data));
+            LY_CHECK_RET(parse_leaf(ctx, in, (struct lysp_node*)grp, &grp->data));
             break;
         case LY_STMT_LEAF_LIST:
-            LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)grp, &grp->data));
+            LY_CHECK_RET(parse_leaflist(ctx, in, (struct lysp_node*)grp, &grp->data));
             break;
         case LY_STMT_LIST:
-            LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)grp, &grp->data));
+            LY_CHECK_RET(parse_list(ctx, in, (struct lysp_node*)grp, &grp->data));
             break;
         case LY_STMT_USES:
-            LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)grp, &grp->data));
+            LY_CHECK_RET(parse_uses(ctx, in, (struct lysp_node*)grp, &grp->data));
             break;
 
         case LY_STMT_TYPEDEF:
-            LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)grp, data, &grp->typedefs));
+            LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)grp, in, &grp->typedefs));
             break;
         case LY_STMT_ACTION:
             PARSER_CHECK_STMTVER2_RET(ctx, "action", "grouping");
-            LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)grp, &grp->actions));
+            LY_CHECK_RET(parse_action(ctx, in, (struct lysp_node*)grp, &grp->actions));
             break;
         case LY_STMT_GROUPING:
-            LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)grp, &grp->groupings));
+            LY_CHECK_RET(parse_grouping(ctx, in, (struct lysp_node*)grp, &grp->groupings));
             break;
         case LY_STMT_NOTIFICATION:
             PARSER_CHECK_STMTVER2_RET(ctx, "notification", "grouping");
-            LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)grp, &grp->notifs));
+            LY_CHECK_RET(parse_notif(ctx, in, (struct lysp_node*)grp, &grp->notifs));
             break;
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &grp->exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &grp->exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "grouping");
@@ -2926,13 +2931,13 @@
  * @brief Parse the augment statement.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in,out] augments Augments to add to.
  *
  * @return LY_ERR values.
  */
 LY_ERR
-parse_augment(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_augment **augments)
+parse_augment(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_node *parent, struct lysp_augment **augments)
 {
     LY_ERR ret = LY_SUCCESS;
     char *buf, *word;
@@ -2943,68 +2948,68 @@
     LY_ARRAY_NEW_RET(ctx->ctx, *augments, aug, LY_EMEM);
 
     /* get value */
-    LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_STR_ARG, NULL, &word, &buf, &word_len));
     CHECK_NONEMPTY(ctx, word_len, "augment");
     INSERT_WORD(ctx, buf, aug->nodeid, word, word_len);
     aug->nodetype = LYS_AUGMENT;
     aug->parent = parent;
 
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, goto checks) {
         switch (kw) {
         case LY_STMT_DESCRIPTION:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &aug->dsc, Y_STR_ARG, &aug->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &aug->dsc, Y_STR_ARG, &aug->exts));
             break;
         case LY_STMT_IF_FEATURE:
-            LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &aug->iffeatures, Y_STR_ARG, &aug->exts));
+            LY_CHECK_RET(parse_text_fields(ctx, in, LYEXT_SUBSTMT_IFFEATURE, &aug->iffeatures, Y_STR_ARG, &aug->exts));
             break;
         case LY_STMT_REFERENCE:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &aug->ref, Y_STR_ARG, &aug->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &aug->ref, Y_STR_ARG, &aug->exts));
             break;
         case LY_STMT_STATUS:
-            LY_CHECK_RET(parse_status(ctx, data, &aug->flags, &aug->exts));
+            LY_CHECK_RET(parse_status(ctx, in, &aug->flags, &aug->exts));
             break;
         case LY_STMT_WHEN:
-            LY_CHECK_RET(parse_when(ctx, data, &aug->when));
+            LY_CHECK_RET(parse_when(ctx, in, &aug->when));
             break;
 
         case LY_STMT_ANYDATA:
             PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "augment");
             /* fall through */
         case LY_STMT_ANYXML:
-            LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)aug, &aug->child));
+            LY_CHECK_RET(parse_any(ctx, in, kw, (struct lysp_node*)aug, &aug->child));
             break;
         case LY_STMT_CASE:
-            LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)aug, &aug->child));
+            LY_CHECK_RET(parse_case(ctx, in, (struct lysp_node*)aug, &aug->child));
             break;
         case LY_STMT_CHOICE:
-            LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)aug, &aug->child));
+            LY_CHECK_RET(parse_choice(ctx, in, (struct lysp_node*)aug, &aug->child));
             break;
         case LY_STMT_CONTAINER:
-            LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)aug, &aug->child));
+            LY_CHECK_RET(parse_container(ctx, in, (struct lysp_node*)aug, &aug->child));
             break;
         case LY_STMT_LEAF:
-            LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)aug, &aug->child));
+            LY_CHECK_RET(parse_leaf(ctx, in, (struct lysp_node*)aug, &aug->child));
             break;
         case LY_STMT_LEAF_LIST:
-            LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)aug, &aug->child));
+            LY_CHECK_RET(parse_leaflist(ctx, in, (struct lysp_node*)aug, &aug->child));
             break;
         case LY_STMT_LIST:
-            LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)aug, &aug->child));
+            LY_CHECK_RET(parse_list(ctx, in, (struct lysp_node*)aug, &aug->child));
             break;
         case LY_STMT_USES:
-            LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)aug, &aug->child));
+            LY_CHECK_RET(parse_uses(ctx, in, (struct lysp_node*)aug, &aug->child));
             break;
 
         case LY_STMT_ACTION:
             PARSER_CHECK_STMTVER2_RET(ctx, "action", "augment");
-            LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)aug, &aug->actions));
+            LY_CHECK_RET(parse_action(ctx, in, (struct lysp_node*)aug, &aug->actions));
             break;
         case LY_STMT_NOTIFICATION:
             PARSER_CHECK_STMTVER2_RET(ctx, "notification", "augment");
-            LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)aug, &aug->notifs));
+            LY_CHECK_RET(parse_notif(ctx, in, (struct lysp_node*)aug, &aug->notifs));
             break;
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &aug->exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &aug->exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "augment");
@@ -3023,13 +3028,13 @@
  * @brief Parse the uses statement.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in,out] siblings Siblings to add to.
  *
  * @return LY_ERR values.
  */
 LY_ERR
-parse_uses(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
+parse_uses(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_node *parent, struct lysp_node **siblings)
 {
     LY_ERR ret = LY_SUCCESS;
     char *buf, *word;
@@ -3043,36 +3048,36 @@
     uses->parent = parent;
 
     /* get name */
-    LY_CHECK_RET(get_argument(ctx, data, Y_PREF_IDENTIF_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_PREF_IDENTIF_ARG, NULL, &word, &buf, &word_len));
     INSERT_WORD(ctx, buf, uses->name, word, word_len);
 
     /* parse substatements */
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, goto checks) {
         switch (kw) {
         case LY_STMT_DESCRIPTION:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &uses->dsc, Y_STR_ARG, &uses->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &uses->dsc, Y_STR_ARG, &uses->exts));
             break;
         case LY_STMT_IF_FEATURE:
-            LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &uses->iffeatures, Y_STR_ARG, &uses->exts));
+            LY_CHECK_RET(parse_text_fields(ctx, in, LYEXT_SUBSTMT_IFFEATURE, &uses->iffeatures, Y_STR_ARG, &uses->exts));
             break;
         case LY_STMT_REFERENCE:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &uses->ref, Y_STR_ARG, &uses->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &uses->ref, Y_STR_ARG, &uses->exts));
             break;
         case LY_STMT_STATUS:
-            LY_CHECK_RET(parse_status(ctx, data, &uses->flags, &uses->exts));
+            LY_CHECK_RET(parse_status(ctx, in, &uses->flags, &uses->exts));
             break;
         case LY_STMT_WHEN:
-            LY_CHECK_RET(parse_when(ctx, data, &uses->when));
+            LY_CHECK_RET(parse_when(ctx, in, &uses->when));
             break;
 
         case LY_STMT_REFINE:
-            LY_CHECK_RET(parse_refine(ctx, data, &uses->refines));
+            LY_CHECK_RET(parse_refine(ctx, in, &uses->refines));
             break;
         case LY_STMT_AUGMENT:
-            LY_CHECK_RET(parse_augment(ctx, data, (struct lysp_node*)uses, &uses->augments));
+            LY_CHECK_RET(parse_augment(ctx, in, (struct lysp_node*)uses, &uses->augments));
             break;
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &uses->exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &uses->exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "uses");
@@ -3090,13 +3095,13 @@
  * @brief Parse the case statement.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in,out] siblings Siblings to add to.
  *
  * @return LY_ERR values.
  */
 LY_ERR
-parse_case(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
+parse_case(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_node *parent, struct lysp_node **siblings)
 {
     LY_ERR ret = LY_SUCCESS;
     char *buf, *word;
@@ -3110,54 +3115,54 @@
     cas->parent = parent;
 
     /* get name */
-    LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
     INSERT_WORD(ctx, buf, cas->name, word, word_len);
 
     /* parse substatements */
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret,) {
         switch (kw) {
         case LY_STMT_DESCRIPTION:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &cas->dsc, Y_STR_ARG, &cas->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &cas->dsc, Y_STR_ARG, &cas->exts));
             break;
         case LY_STMT_IF_FEATURE:
-            LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &cas->iffeatures, Y_STR_ARG, &cas->exts));
+            LY_CHECK_RET(parse_text_fields(ctx, in, LYEXT_SUBSTMT_IFFEATURE, &cas->iffeatures, Y_STR_ARG, &cas->exts));
             break;
         case LY_STMT_REFERENCE:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &cas->ref, Y_STR_ARG, &cas->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &cas->ref, Y_STR_ARG, &cas->exts));
             break;
         case LY_STMT_STATUS:
-            LY_CHECK_RET(parse_status(ctx, data, &cas->flags, &cas->exts));
+            LY_CHECK_RET(parse_status(ctx, in, &cas->flags, &cas->exts));
             break;
         case LY_STMT_WHEN:
-            LY_CHECK_RET(parse_when(ctx, data, &cas->when));
+            LY_CHECK_RET(parse_when(ctx, in, &cas->when));
             break;
 
         case LY_STMT_ANYDATA:
             PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "case");
             /* fall through */
         case LY_STMT_ANYXML:
-            LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cas, &cas->child));
+            LY_CHECK_RET(parse_any(ctx, in, kw, (struct lysp_node*)cas, &cas->child));
             break;
         case LY_STMT_CHOICE:
-            LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)cas, &cas->child));
+            LY_CHECK_RET(parse_choice(ctx, in, (struct lysp_node*)cas, &cas->child));
             break;
         case LY_STMT_CONTAINER:
-            LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cas, &cas->child));
+            LY_CHECK_RET(parse_container(ctx, in, (struct lysp_node*)cas, &cas->child));
             break;
         case LY_STMT_LEAF:
-            LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cas, &cas->child));
+            LY_CHECK_RET(parse_leaf(ctx, in, (struct lysp_node*)cas, &cas->child));
             break;
         case LY_STMT_LEAF_LIST:
-            LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cas, &cas->child));
+            LY_CHECK_RET(parse_leaflist(ctx, in, (struct lysp_node*)cas, &cas->child));
             break;
         case LY_STMT_LIST:
-            LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cas, &cas->child));
+            LY_CHECK_RET(parse_list(ctx, in, (struct lysp_node*)cas, &cas->child));
             break;
         case LY_STMT_USES:
-            LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cas, &cas->child));
+            LY_CHECK_RET(parse_uses(ctx, in, (struct lysp_node*)cas, &cas->child));
             break;
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cas->exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cas->exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "case");
@@ -3171,13 +3176,13 @@
  * @brief Parse the choice statement.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in,out] siblings Siblings to add to.
  *
  * @return LY_ERR values.
  */
 LY_ERR
-parse_choice(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
+parse_choice(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_node *parent, struct lysp_node **siblings)
 {
     LY_ERR ret = LY_SUCCESS;
     char *buf, *word;
@@ -3191,64 +3196,64 @@
     choice->parent = parent;
 
     /* get name */
-    LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
     INSERT_WORD(ctx, buf, choice->name, word, word_len);
 
     /* parse substatements */
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, goto checks) {
         switch (kw) {
         case LY_STMT_CONFIG:
-            LY_CHECK_RET(parse_config(ctx, data, &choice->flags, &choice->exts));
+            LY_CHECK_RET(parse_config(ctx, in, &choice->flags, &choice->exts));
             break;
         case LY_STMT_DESCRIPTION:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &choice->dsc, Y_STR_ARG, &choice->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &choice->dsc, Y_STR_ARG, &choice->exts));
             break;
         case LY_STMT_IF_FEATURE:
-            LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &choice->iffeatures, Y_STR_ARG, &choice->exts));
+            LY_CHECK_RET(parse_text_fields(ctx, in, LYEXT_SUBSTMT_IFFEATURE, &choice->iffeatures, Y_STR_ARG, &choice->exts));
             break;
         case LY_STMT_MANDATORY:
-            LY_CHECK_RET(parse_mandatory(ctx, data, &choice->flags, &choice->exts));
+            LY_CHECK_RET(parse_mandatory(ctx, in, &choice->flags, &choice->exts));
             break;
         case LY_STMT_REFERENCE:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &choice->ref, Y_STR_ARG, &choice->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &choice->ref, Y_STR_ARG, &choice->exts));
             break;
         case LY_STMT_STATUS:
-            LY_CHECK_RET(parse_status(ctx, data, &choice->flags, &choice->exts));
+            LY_CHECK_RET(parse_status(ctx, in, &choice->flags, &choice->exts));
             break;
         case LY_STMT_WHEN:
-            LY_CHECK_RET(parse_when(ctx, data, &choice->when));
+            LY_CHECK_RET(parse_when(ctx, in, &choice->when));
             break;
         case LY_STMT_DEFAULT:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &choice->dflt, Y_PREF_IDENTIF_ARG, &choice->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DEFAULT, 0, &choice->dflt, Y_PREF_IDENTIF_ARG, &choice->exts));
             break;
 
         case LY_STMT_ANYDATA:
             PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "choice");
             /* fall through */
         case LY_STMT_ANYXML:
-            LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)choice, &choice->child));
+            LY_CHECK_RET(parse_any(ctx, in, kw, (struct lysp_node*)choice, &choice->child));
             break;
         case LY_STMT_CASE:
-            LY_CHECK_RET(parse_case(ctx, data, (struct lysp_node*)choice, &choice->child));
+            LY_CHECK_RET(parse_case(ctx, in, (struct lysp_node*)choice, &choice->child));
             break;
         case LY_STMT_CHOICE:
             PARSER_CHECK_STMTVER2_RET(ctx, "choice", "choice");
-            LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)choice, &choice->child));
+            LY_CHECK_RET(parse_choice(ctx, in, (struct lysp_node*)choice, &choice->child));
             break;
         case LY_STMT_CONTAINER:
-            LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)choice, &choice->child));
+            LY_CHECK_RET(parse_container(ctx, in, (struct lysp_node*)choice, &choice->child));
             break;
         case LY_STMT_LEAF:
-            LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)choice, &choice->child));
+            LY_CHECK_RET(parse_leaf(ctx, in, (struct lysp_node*)choice, &choice->child));
             break;
         case LY_STMT_LEAF_LIST:
-            LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)choice, &choice->child));
+            LY_CHECK_RET(parse_leaflist(ctx, in, (struct lysp_node*)choice, &choice->child));
             break;
         case LY_STMT_LIST:
-            LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)choice, &choice->child));
+            LY_CHECK_RET(parse_list(ctx, in, (struct lysp_node*)choice, &choice->child));
             break;
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &choice->exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &choice->exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "choice");
@@ -3268,13 +3273,13 @@
  * @brief Parse the container statement.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in,out] siblings Siblings to add to.
  *
  * @return LY_ERR values.
  */
 LY_ERR
-parse_container(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
+parse_container(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_node *parent, struct lysp_node **siblings)
 {
     LY_ERR ret = 0;
     char *buf, *word;
@@ -3288,78 +3293,78 @@
     cont->parent = parent;
 
     /* get name */
-    LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
     INSERT_WORD(ctx, buf, cont->name, word, word_len);
 
     /* parse substatements */
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, goto checks) {
         switch (kw) {
         case LY_STMT_CONFIG:
-            LY_CHECK_RET(parse_config(ctx, data, &cont->flags, &cont->exts));
+            LY_CHECK_RET(parse_config(ctx, in, &cont->flags, &cont->exts));
             break;
         case LY_STMT_DESCRIPTION:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &cont->dsc, Y_STR_ARG, &cont->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &cont->dsc, Y_STR_ARG, &cont->exts));
             break;
         case LY_STMT_IF_FEATURE:
-            LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &cont->iffeatures, Y_STR_ARG, &cont->exts));
+            LY_CHECK_RET(parse_text_fields(ctx, in, LYEXT_SUBSTMT_IFFEATURE, &cont->iffeatures, Y_STR_ARG, &cont->exts));
             break;
         case LY_STMT_REFERENCE:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &cont->ref, Y_STR_ARG, &cont->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &cont->ref, Y_STR_ARG, &cont->exts));
             break;
         case LY_STMT_STATUS:
-            LY_CHECK_RET(parse_status(ctx, data, &cont->flags, &cont->exts));
+            LY_CHECK_RET(parse_status(ctx, in, &cont->flags, &cont->exts));
             break;
         case LY_STMT_WHEN:
-            LY_CHECK_RET(parse_when(ctx, data, &cont->when));
+            LY_CHECK_RET(parse_when(ctx, in, &cont->when));
             break;
         case LY_STMT_PRESENCE:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_PRESENCE, 0, &cont->presence, Y_STR_ARG, &cont->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_PRESENCE, 0, &cont->presence, Y_STR_ARG, &cont->exts));
             break;
 
         case LY_STMT_ANYDATA:
             PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "container");
             /* fall through */
         case LY_STMT_ANYXML:
-            LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)cont, &cont->child));
+            LY_CHECK_RET(parse_any(ctx, in, kw, (struct lysp_node*)cont, &cont->child));
             break;
         case LY_STMT_CHOICE:
-            LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)cont, &cont->child));
+            LY_CHECK_RET(parse_choice(ctx, in, (struct lysp_node*)cont, &cont->child));
             break;
         case LY_STMT_CONTAINER:
-            LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)cont, &cont->child));
+            LY_CHECK_RET(parse_container(ctx, in, (struct lysp_node*)cont, &cont->child));
             break;
         case LY_STMT_LEAF:
-            LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)cont, &cont->child));
+            LY_CHECK_RET(parse_leaf(ctx, in, (struct lysp_node*)cont, &cont->child));
             break;
         case LY_STMT_LEAF_LIST:
-            LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)cont, &cont->child));
+            LY_CHECK_RET(parse_leaflist(ctx, in, (struct lysp_node*)cont, &cont->child));
             break;
         case LY_STMT_LIST:
-            LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)cont, &cont->child));
+            LY_CHECK_RET(parse_list(ctx, in, (struct lysp_node*)cont, &cont->child));
             break;
         case LY_STMT_USES:
-            LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)cont, &cont->child));
+            LY_CHECK_RET(parse_uses(ctx, in, (struct lysp_node*)cont, &cont->child));
             break;
 
         case LY_STMT_TYPEDEF:
-            LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)cont, data, &cont->typedefs));
+            LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)cont, in, &cont->typedefs));
             break;
         case LY_STMT_MUST:
-            LY_CHECK_RET(parse_restrs(ctx, data, kw, &cont->musts));
+            LY_CHECK_RET(parse_restrs(ctx, in, kw, &cont->musts));
             break;
         case LY_STMT_ACTION:
             PARSER_CHECK_STMTVER2_RET(ctx, "action", "container");
-            LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)cont, &cont->actions));
+            LY_CHECK_RET(parse_action(ctx, in, (struct lysp_node*)cont, &cont->actions));
             break;
         case LY_STMT_GROUPING:
-            LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)cont, &cont->groupings));
+            LY_CHECK_RET(parse_grouping(ctx, in, (struct lysp_node*)cont, &cont->groupings));
             break;
         case LY_STMT_NOTIFICATION:
             PARSER_CHECK_STMTVER2_RET(ctx, "notification", "container");
-            LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)cont, &cont->notifs));
+            LY_CHECK_RET(parse_notif(ctx, in, (struct lysp_node*)cont, &cont->notifs));
             break;
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cont->exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &cont->exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "container");
@@ -3376,13 +3381,13 @@
  * @brief Parse the list statement.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in,out] siblings Siblings to add to.
  *
  * @return LY_ERR values.
  */
 LY_ERR
-parse_list(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings)
+parse_list(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_node *parent, struct lysp_node **siblings)
 {
     LY_ERR ret = LY_SUCCESS;
     char *buf, *word;
@@ -3396,90 +3401,90 @@
     list->parent = parent;
 
     /* get name */
-    LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
     INSERT_WORD(ctx, buf, list->name, word, word_len);
 
     /* parse substatements */
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, goto checks) {
         switch (kw) {
         case LY_STMT_CONFIG:
-            LY_CHECK_RET(parse_config(ctx, data, &list->flags, &list->exts));
+            LY_CHECK_RET(parse_config(ctx, in, &list->flags, &list->exts));
             break;
         case LY_STMT_DESCRIPTION:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &list->dsc, Y_STR_ARG, &list->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &list->dsc, Y_STR_ARG, &list->exts));
             break;
         case LY_STMT_IF_FEATURE:
-            LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &list->iffeatures, Y_STR_ARG, &list->exts));
+            LY_CHECK_RET(parse_text_fields(ctx, in, LYEXT_SUBSTMT_IFFEATURE, &list->iffeatures, Y_STR_ARG, &list->exts));
             break;
         case LY_STMT_REFERENCE:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &list->ref, Y_STR_ARG, &list->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &list->ref, Y_STR_ARG, &list->exts));
             break;
         case LY_STMT_STATUS:
-            LY_CHECK_RET(parse_status(ctx, data, &list->flags, &list->exts));
+            LY_CHECK_RET(parse_status(ctx, in, &list->flags, &list->exts));
             break;
         case LY_STMT_WHEN:
-            LY_CHECK_RET(parse_when(ctx, data, &list->when));
+            LY_CHECK_RET(parse_when(ctx, in, &list->when));
             break;
         case LY_STMT_KEY:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_KEY, 0, &list->key, Y_STR_ARG, &list->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_KEY, 0, &list->key, Y_STR_ARG, &list->exts));
             break;
         case LY_STMT_MAX_ELEMENTS:
-            LY_CHECK_RET(parse_maxelements(ctx, data, &list->max, &list->flags, &list->exts));
+            LY_CHECK_RET(parse_maxelements(ctx, in, &list->max, &list->flags, &list->exts));
             break;
         case LY_STMT_MIN_ELEMENTS:
-            LY_CHECK_RET(parse_minelements(ctx, data, &list->min, &list->flags, &list->exts));
+            LY_CHECK_RET(parse_minelements(ctx, in, &list->min, &list->flags, &list->exts));
             break;
         case LY_STMT_ORDERED_BY:
-            LY_CHECK_RET(parse_orderedby(ctx, data, &list->flags, &list->exts));
+            LY_CHECK_RET(parse_orderedby(ctx, in, &list->flags, &list->exts));
             break;
         case LY_STMT_UNIQUE:
-            LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_UNIQUE, &list->uniques, Y_STR_ARG, &list->exts));
+            LY_CHECK_RET(parse_text_fields(ctx, in, LYEXT_SUBSTMT_UNIQUE, &list->uniques, Y_STR_ARG, &list->exts));
             break;
 
         case LY_STMT_ANYDATA:
             PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "list");
             /* fall through */
         case LY_STMT_ANYXML:
-            LY_CHECK_RET(parse_any(ctx, data, kw, (struct lysp_node*)list, &list->child));
+            LY_CHECK_RET(parse_any(ctx, in, kw, (struct lysp_node*)list, &list->child));
             break;
         case LY_STMT_CHOICE:
-            LY_CHECK_RET(parse_choice(ctx, data, (struct lysp_node*)list, &list->child));
+            LY_CHECK_RET(parse_choice(ctx, in, (struct lysp_node*)list, &list->child));
             break;
         case LY_STMT_CONTAINER:
-            LY_CHECK_RET(parse_container(ctx, data, (struct lysp_node*)list, &list->child));
+            LY_CHECK_RET(parse_container(ctx, in, (struct lysp_node*)list, &list->child));
             break;
         case LY_STMT_LEAF:
-            LY_CHECK_RET(parse_leaf(ctx, data, (struct lysp_node*)list, &list->child));
+            LY_CHECK_RET(parse_leaf(ctx, in, (struct lysp_node*)list, &list->child));
             break;
         case LY_STMT_LEAF_LIST:
-            LY_CHECK_RET(parse_leaflist(ctx, data, (struct lysp_node*)list, &list->child));
+            LY_CHECK_RET(parse_leaflist(ctx, in, (struct lysp_node*)list, &list->child));
             break;
         case LY_STMT_LIST:
-            LY_CHECK_RET(parse_list(ctx, data, (struct lysp_node*)list, &list->child));
+            LY_CHECK_RET(parse_list(ctx, in, (struct lysp_node*)list, &list->child));
             break;
         case LY_STMT_USES:
-            LY_CHECK_RET(parse_uses(ctx, data, (struct lysp_node*)list, &list->child));
+            LY_CHECK_RET(parse_uses(ctx, in, (struct lysp_node*)list, &list->child));
             break;
 
         case LY_STMT_TYPEDEF:
-            LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)list, data, &list->typedefs));
+            LY_CHECK_RET(parse_typedef(ctx, (struct lysp_node*)list, in, &list->typedefs));
             break;
         case LY_STMT_MUST:
-            LY_CHECK_RET(parse_restrs(ctx, data, kw, &list->musts));
+            LY_CHECK_RET(parse_restrs(ctx, in, kw, &list->musts));
             break;
         case LY_STMT_ACTION:
             PARSER_CHECK_STMTVER2_RET(ctx, "action", "list");
-            LY_CHECK_RET(parse_action(ctx, data, (struct lysp_node*)list, &list->actions));
+            LY_CHECK_RET(parse_action(ctx, in, (struct lysp_node*)list, &list->actions));
             break;
         case LY_STMT_GROUPING:
-            LY_CHECK_RET(parse_grouping(ctx, data, (struct lysp_node*)list, &list->groupings));
+            LY_CHECK_RET(parse_grouping(ctx, in, (struct lysp_node*)list, &list->groupings));
             break;
         case LY_STMT_NOTIFICATION:
             PARSER_CHECK_STMTVER2_RET(ctx, "notification", "list");
-            LY_CHECK_RET(parse_notif(ctx, data, (struct lysp_node*)list, &list->notifs));
+            LY_CHECK_RET(parse_notif(ctx, in, (struct lysp_node*)list, &list->notifs));
             break;
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &list->exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &list->exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "list");
@@ -3505,14 +3510,14 @@
  * @brief Parse the yin-element statement.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in,out] flags Flags to write to.
  * @param[in,out] exts Extension instances to add to.
  *
  * @return LY_ERR values.
  */
 static LY_ERR
-parse_yinelement(struct lys_yang_parser_ctx *ctx, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
+parse_yinelement(struct lys_yang_parser_ctx *ctx, struct ly_in *in, uint16_t *flags, struct lysp_ext_instance **exts)
 {
     LY_ERR ret = LY_SUCCESS;
     char *buf, *word;
@@ -3525,7 +3530,7 @@
     }
 
     /* get value */
-    LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_STR_ARG, NULL, &word, &buf, &word_len));
 
     if ((word_len == 4) && !strncmp(word, "true", word_len)) {
         *flags |= LYS_YINELEM_TRUE;
@@ -3538,10 +3543,10 @@
     }
     free(buf);
 
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret,) {
         switch (kw) {
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_YINELEM, 0, exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_YINELEM, 0, exts));
             LY_CHECK_RET(ret);            break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "yin-element");
@@ -3555,7 +3560,7 @@
  * @brief Parse the argument statement.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in,out] argument Value to write to.
  * @param[in,out] flags Flags to write to.
  * @param[in,out] exts Extension instances to add to.
@@ -3563,7 +3568,7 @@
  * @return LY_ERR values.
  */
 static LY_ERR
-parse_argument(struct lys_yang_parser_ctx *ctx, const char **data, const char **argument, uint16_t *flags, struct lysp_ext_instance **exts)
+parse_argument(struct lys_yang_parser_ctx *ctx, struct ly_in *in, const char **argument, uint16_t *flags, struct lysp_ext_instance **exts)
 {
     LY_ERR ret = LY_SUCCESS;
     char *buf, *word;
@@ -3576,16 +3581,16 @@
     }
 
     /* get value */
-    LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
     INSERT_WORD(ctx, buf, *argument, word, word_len);
 
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret,) {
         switch (kw) {
         case LY_STMT_YIN_ELEMENT:
-            LY_CHECK_RET(parse_yinelement(ctx, data, flags, exts));
+            LY_CHECK_RET(parse_yinelement(ctx, in, flags, exts));
             break;
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_ARGUMENT, 0, exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_ARGUMENT, 0, exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "argument");
@@ -3599,13 +3604,13 @@
  * @brief Parse the extension statement.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in,out] extensions Extensions to add to.
  *
  * @return LY_ERR values.
  */
 static LY_ERR
-parse_extension(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_ext **extensions)
+parse_extension(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_ext **extensions)
 {
     LY_ERR ret = LY_SUCCESS;
     char *buf, *word;
@@ -3616,25 +3621,25 @@
     LY_ARRAY_NEW_RET(ctx->ctx, *extensions, ex, LY_EMEM);
 
     /* get value */
-    LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
     INSERT_WORD(ctx, buf, ex->name, word, word_len);
 
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret,) {
         switch (kw) {
         case LY_STMT_DESCRIPTION:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &ex->dsc, Y_STR_ARG, &ex->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &ex->dsc, Y_STR_ARG, &ex->exts));
             break;
         case LY_STMT_REFERENCE:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &ex->ref, Y_STR_ARG, &ex->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &ex->ref, Y_STR_ARG, &ex->exts));
             break;
         case LY_STMT_STATUS:
-            LY_CHECK_RET(parse_status(ctx, data, &ex->flags, &ex->exts));
+            LY_CHECK_RET(parse_status(ctx, in, &ex->flags, &ex->exts));
             break;
         case LY_STMT_ARGUMENT:
-            LY_CHECK_RET(parse_argument(ctx, data, &ex->argument, &ex->flags, &ex->exts));
+            LY_CHECK_RET(parse_argument(ctx, in, &ex->argument, &ex->flags, &ex->exts));
             break;
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ex->exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ex->exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "extension");
@@ -3648,13 +3653,13 @@
  * @brief Parse the deviate statement.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in,out] deviates Deviates to add to.
  *
  * @return LY_ERR values.
  */
 LY_ERR
-parse_deviate(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_deviate **deviates)
+parse_deviate(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_deviate **deviates)
 {
     LY_ERR ret = LY_SUCCESS;
     char *buf, *word;
@@ -3670,7 +3675,7 @@
     uint32_t *d_min = 0, *d_max = 0;
 
     /* get value */
-    LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_STR_ARG, NULL, &word, &buf, &word_len));
 
     if ((word_len == 13) && !strncmp(word, "not-supported", word_len)) {
         dev_mod = LYS_DEV_NOT_SUPPORTED;
@@ -3732,7 +3737,7 @@
     /* insert into siblings */
     LY_LIST_INSERT(deviates, d, next);
 
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret,) {
         switch (kw) {
         case LY_STMT_CONFIG:
             switch (dev_mod) {
@@ -3741,7 +3746,7 @@
                 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
                 return LY_EVALID;
             default:
-                LY_CHECK_RET(parse_config(ctx, data, d_flags, &d->exts));
+                LY_CHECK_RET(parse_config(ctx, in, d_flags, &d->exts));
                 break;
             }
             break;
@@ -3751,10 +3756,10 @@
                 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
                 return LY_EVALID;
             case LYS_DEV_REPLACE:
-                LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DEFAULT, 0, &d_rpl->dflt, Y_STR_ARG, &d->exts));
+                LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DEFAULT, 0, &d_rpl->dflt, Y_STR_ARG, &d->exts));
                 break;
             default:
-                LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_DEFAULT, d_dflts, Y_STR_ARG, &d->exts));
+                LY_CHECK_RET(parse_text_fields(ctx, in, LYEXT_SUBSTMT_DEFAULT, d_dflts, Y_STR_ARG, &d->exts));
                 break;
             }
             break;
@@ -3765,7 +3770,7 @@
                 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
                 return LY_EVALID;
             default:
-                LY_CHECK_RET(parse_mandatory(ctx, data, d_flags, &d->exts));
+                LY_CHECK_RET(parse_mandatory(ctx, in, d_flags, &d->exts));
                 break;
             }
             break;
@@ -3776,7 +3781,7 @@
                 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
                 return LY_EVALID;
             default:
-                LY_CHECK_RET(parse_maxelements(ctx, data, d_max, d_flags, &d->exts));
+                LY_CHECK_RET(parse_maxelements(ctx, in, d_max, d_flags, &d->exts));
                 break;
             }
             break;
@@ -3787,7 +3792,7 @@
                 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
                 return LY_EVALID;
             default:
-                LY_CHECK_RET(parse_minelements(ctx, data, d_min, d_flags, &d->exts));
+                LY_CHECK_RET(parse_minelements(ctx, in, d_min, d_flags, &d->exts));
                 break;
             }
             break;
@@ -3798,7 +3803,7 @@
                 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
                 return LY_EVALID;
             default:
-                LY_CHECK_RET(parse_restrs(ctx, data, kw, d_musts));
+                LY_CHECK_RET(parse_restrs(ctx, in, kw, d_musts));
                 break;
             }
             break;
@@ -3816,7 +3821,7 @@
                 }
                 d_rpl->type = calloc(1, sizeof *d_rpl->type);
                 LY_CHECK_ERR_RET(!d_rpl->type, LOGMEM(ctx->ctx), LY_EMEM);
-                LY_CHECK_RET(parse_type(ctx, data, d_rpl->type));
+                LY_CHECK_RET(parse_type(ctx, in, d_rpl->type));
                 break;
             }
             break;
@@ -3827,7 +3832,7 @@
                 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
                 return LY_EVALID;
             default:
-                LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_UNIQUE, d_uniques, Y_STR_ARG, &d->exts));
+                LY_CHECK_RET(parse_text_fields(ctx, in, LYEXT_SUBSTMT_UNIQUE, d_uniques, Y_STR_ARG, &d->exts));
                 break;
             }
             break;
@@ -3837,12 +3842,12 @@
                 LOGVAL_PARSER(ctx, LY_VCODE_INDEV, ly_devmod2str(dev_mod), ly_stmt2str(kw));
                 return LY_EVALID;
             default:
-                LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_UNITS, 0, d_units, Y_STR_ARG, &d->exts));
+                LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_UNITS, 0, d_units, Y_STR_ARG, &d->exts));
                 break;
             }
             break;
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &d->exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &d->exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviate");
@@ -3856,13 +3861,13 @@
  * @brief Parse the deviation statement.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in,out] deviations Deviations to add to.
  *
  * @return LY_ERR values.
  */
 LY_ERR
-parse_deviation(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_deviation **deviations)
+parse_deviation(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_deviation **deviations)
 {
     LY_ERR ret = LY_SUCCESS;
     char *buf, *word;
@@ -3873,23 +3878,23 @@
     LY_ARRAY_NEW_RET(ctx->ctx, *deviations, dev, LY_EMEM);
 
     /* get value */
-    LY_CHECK_RET(get_argument(ctx, data, Y_STR_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_STR_ARG, NULL, &word, &buf, &word_len));
     CHECK_NONEMPTY(ctx, word_len, "deviation");
     INSERT_WORD(ctx, buf, dev->nodeid, word, word_len);
 
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, goto checks) {
         switch (kw) {
         case LY_STMT_DESCRIPTION:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &dev->dsc, Y_STR_ARG, &dev->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &dev->dsc, Y_STR_ARG, &dev->exts));
             break;
         case LY_STMT_DEVIATE:
-            LY_CHECK_RET(parse_deviate(ctx, data, &dev->deviates));
+            LY_CHECK_RET(parse_deviate(ctx, in, &dev->deviates));
             break;
         case LY_STMT_REFERENCE:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &dev->ref, Y_STR_ARG, &dev->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &dev->ref, Y_STR_ARG, &dev->exts));
             break;
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &dev->exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &dev->exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "deviation");
@@ -3911,13 +3916,13 @@
  * @brief Parse the feature statement.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in,out] features Features to add to.
  *
  * @return LY_ERR values.
  */
 LY_ERR
-parse_feature(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_feature **features)
+parse_feature(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_feature **features)
 {
     LY_ERR ret = LY_SUCCESS;
     char *buf, *word;
@@ -3928,25 +3933,25 @@
     LY_ARRAY_NEW_RET(ctx->ctx, *features, feat, LY_EMEM);
 
     /* get value */
-    LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
     INSERT_WORD(ctx, buf, feat->name, word, word_len);
 
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret,) {
         switch (kw) {
         case LY_STMT_DESCRIPTION:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &feat->dsc, Y_STR_ARG, &feat->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &feat->dsc, Y_STR_ARG, &feat->exts));
             break;
         case LY_STMT_IF_FEATURE:
-            LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &feat->iffeatures, Y_STR_ARG, &feat->exts));
+            LY_CHECK_RET(parse_text_fields(ctx, in, LYEXT_SUBSTMT_IFFEATURE, &feat->iffeatures, Y_STR_ARG, &feat->exts));
             break;
         case LY_STMT_REFERENCE:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &feat->ref, Y_STR_ARG, &feat->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &feat->ref, Y_STR_ARG, &feat->exts));
             break;
         case LY_STMT_STATUS:
-            LY_CHECK_RET(parse_status(ctx, data, &feat->flags, &feat->exts));
+            LY_CHECK_RET(parse_status(ctx, in, &feat->flags, &feat->exts));
             break;
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &feat->exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &feat->exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "feature");
@@ -3960,13 +3965,13 @@
  * @brief Parse the identity statement.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in,out] identities Identities to add to.
  *
  * @return LY_ERR values.
  */
 LY_ERR
-parse_identity(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_ident **identities)
+parse_identity(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_ident **identities)
 {
     LY_ERR ret = LY_SUCCESS;
     char *buf, *word;
@@ -3977,33 +3982,33 @@
     LY_ARRAY_NEW_RET(ctx->ctx, *identities, ident, LY_EMEM);
 
     /* get value */
-    LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
     INSERT_WORD(ctx, buf, ident->name, word, word_len);
 
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret,) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret,) {
         switch (kw) {
         case LY_STMT_DESCRIPTION:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &ident->dsc, Y_STR_ARG, &ident->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &ident->dsc, Y_STR_ARG, &ident->exts));
             break;
         case LY_STMT_IF_FEATURE:
             PARSER_CHECK_STMTVER2_RET(ctx, "if-feature", "identity");
-            LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_IFFEATURE, &ident->iffeatures, Y_STR_ARG, &ident->exts));
+            LY_CHECK_RET(parse_text_fields(ctx, in, LYEXT_SUBSTMT_IFFEATURE, &ident->iffeatures, Y_STR_ARG, &ident->exts));
             break;
         case LY_STMT_REFERENCE:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &ident->ref, Y_STR_ARG, &ident->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &ident->ref, Y_STR_ARG, &ident->exts));
             break;
         case LY_STMT_STATUS:
-            LY_CHECK_RET(parse_status(ctx, data, &ident->flags, &ident->exts));
+            LY_CHECK_RET(parse_status(ctx, in, &ident->flags, &ident->exts));
             break;
         case LY_STMT_BASE:
             if (ident->bases && ctx->mod_version < 2) {
                 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YANG, "Identity can be derived from multiple base identities only in YANG 1.1 modules");
                 return LY_EVALID;
             }
-            LY_CHECK_RET(parse_text_fields(ctx, data, LYEXT_SUBSTMT_BASE, &ident->bases, Y_PREF_IDENTIF_ARG, &ident->exts));
+            LY_CHECK_RET(parse_text_fields(ctx, in, LYEXT_SUBSTMT_BASE, &ident->bases, Y_PREF_IDENTIF_ARG, &ident->exts));
             break;
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ident->exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &ident->exts));
             break;
         default:
             LOGVAL_PARSER(ctx, LY_VCODE_INCHILDSTMT, ly_stmt2str(kw), "identity");
@@ -4017,13 +4022,13 @@
  * @brief Parse module substatements.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[in,out] mod Module to write to.
  *
  * @return LY_ERR values.
  */
 LY_ERR
-parse_module(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_module *mod)
+parse_module(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_module *mod)
 {
     LY_ERR ret = 0;
     char *buf, *word;
@@ -4033,10 +4038,10 @@
     struct lysp_submodule *dup;
 
     /* (sub)module name */
-    LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
     INSERT_WORD(ctx, buf, mod->mod->name, word, word_len);
 
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, goto checks) {
 
 #define CHECK_ORDER(SECTION) \
         if (mod_stmt > SECTION) {LOGVAL_PARSER(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw)); return LY_EVALID;}mod_stmt = SECTION
@@ -4098,41 +4103,41 @@
         switch (kw) {
         /* module header */
         case LY_STMT_YANG_VERSION:
-            LY_CHECK_RET(parse_yangversion(ctx, data, &mod->mod->version, &mod->exts));
+            LY_CHECK_RET(parse_yangversion(ctx, in, &mod->mod->version, &mod->exts));
             ctx->mod_version = mod->mod->version;
             break;
         case LY_STMT_NAMESPACE:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_NAMESPACE, 0, &mod->mod->ns, Y_STR_ARG, &mod->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_NAMESPACE, 0, &mod->mod->ns, Y_STR_ARG, &mod->exts));
             break;
         case LY_STMT_PREFIX:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, &mod->mod->prefix, Y_IDENTIF_ARG, &mod->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_PREFIX, 0, &mod->mod->prefix, Y_IDENTIF_ARG, &mod->exts));
             break;
 
         /* linkage */
         case LY_STMT_INCLUDE:
-            LY_CHECK_RET(parse_include(ctx, mod->mod->name, data, &mod->includes));
+            LY_CHECK_RET(parse_include(ctx, mod->mod->name, in, &mod->includes));
             break;
         case LY_STMT_IMPORT:
-            LY_CHECK_RET(parse_import(ctx, mod->mod->prefix, data, &mod->imports));
+            LY_CHECK_RET(parse_import(ctx, mod->mod->prefix, in, &mod->imports));
             break;
 
         /* meta */
         case LY_STMT_ORGANIZATION:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_ORGANIZATION, 0, &mod->mod->org, Y_STR_ARG, &mod->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_ORGANIZATION, 0, &mod->mod->org, Y_STR_ARG, &mod->exts));
             break;
         case LY_STMT_CONTACT:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_CONTACT, 0, &mod->mod->contact, Y_STR_ARG, &mod->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_CONTACT, 0, &mod->mod->contact, Y_STR_ARG, &mod->exts));
             break;
         case LY_STMT_DESCRIPTION:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &mod->mod->dsc, Y_STR_ARG, &mod->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &mod->mod->dsc, Y_STR_ARG, &mod->exts));
             break;
         case LY_STMT_REFERENCE:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &mod->mod->ref, Y_STR_ARG, &mod->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &mod->mod->ref, Y_STR_ARG, &mod->exts));
             break;
 
         /* revision */
         case LY_STMT_REVISION:
-            LY_CHECK_RET(parse_revision(ctx, data, &mod->revs));
+            LY_CHECK_RET(parse_revision(ctx, in, &mod->revs));
             break;
 
         /* body */
@@ -4140,56 +4145,56 @@
             PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "module");
             /* fall through */
         case LY_STMT_ANYXML:
-            LY_CHECK_RET(parse_any(ctx, data, kw, NULL, &mod->data));
+            LY_CHECK_RET(parse_any(ctx, in, kw, NULL, &mod->data));
             break;
         case LY_STMT_CHOICE:
-            LY_CHECK_RET(parse_choice(ctx, data, NULL, &mod->data));
+            LY_CHECK_RET(parse_choice(ctx, in, NULL, &mod->data));
             break;
         case LY_STMT_CONTAINER:
-            LY_CHECK_RET(parse_container(ctx, data, NULL, &mod->data));
+            LY_CHECK_RET(parse_container(ctx, in, NULL, &mod->data));
             break;
         case LY_STMT_LEAF:
-            LY_CHECK_RET(parse_leaf(ctx, data, NULL, &mod->data));
+            LY_CHECK_RET(parse_leaf(ctx, in, NULL, &mod->data));
             break;
         case LY_STMT_LEAF_LIST:
-            LY_CHECK_RET(parse_leaflist(ctx, data, NULL, &mod->data));
+            LY_CHECK_RET(parse_leaflist(ctx, in, NULL, &mod->data));
             break;
         case LY_STMT_LIST:
-            LY_CHECK_RET(parse_list(ctx, data, NULL, &mod->data));
+            LY_CHECK_RET(parse_list(ctx, in, NULL, &mod->data));
             break;
         case LY_STMT_USES:
-            LY_CHECK_RET(parse_uses(ctx, data, NULL, &mod->data));
+            LY_CHECK_RET(parse_uses(ctx, in, NULL, &mod->data));
             break;
 
         case LY_STMT_AUGMENT:
-            LY_CHECK_RET(parse_augment(ctx, data, NULL, &mod->augments));
+            LY_CHECK_RET(parse_augment(ctx, in, NULL, &mod->augments));
             break;
         case LY_STMT_DEVIATION:
-            LY_CHECK_RET(parse_deviation(ctx, data, &mod->deviations));
+            LY_CHECK_RET(parse_deviation(ctx, in, &mod->deviations));
             break;
         case LY_STMT_EXTENSION:
-            LY_CHECK_RET(parse_extension(ctx, data, &mod->extensions));
+            LY_CHECK_RET(parse_extension(ctx, in, &mod->extensions));
             break;
         case LY_STMT_FEATURE:
-            LY_CHECK_RET(parse_feature(ctx, data, &mod->features));
+            LY_CHECK_RET(parse_feature(ctx, in, &mod->features));
             break;
         case LY_STMT_GROUPING:
-            LY_CHECK_RET(parse_grouping(ctx, data, NULL, &mod->groupings));
+            LY_CHECK_RET(parse_grouping(ctx, in, NULL, &mod->groupings));
             break;
         case LY_STMT_IDENTITY:
-            LY_CHECK_RET(parse_identity(ctx, data, &mod->identities));
+            LY_CHECK_RET(parse_identity(ctx, in, &mod->identities));
             break;
         case LY_STMT_NOTIFICATION:
-            LY_CHECK_RET(parse_notif(ctx, data, NULL, &mod->notifs));
+            LY_CHECK_RET(parse_notif(ctx, in, NULL, &mod->notifs));
             break;
         case LY_STMT_RPC:
-            LY_CHECK_RET(parse_action(ctx, data, NULL, &mod->rpcs));
+            LY_CHECK_RET(parse_action(ctx, in, NULL, &mod->rpcs));
             break;
         case LY_STMT_TYPEDEF:
-            LY_CHECK_RET(parse_typedef(ctx, NULL, data, &mod->typedefs));
+            LY_CHECK_RET(parse_typedef(ctx, NULL, in, &mod->typedefs));
             break;
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &mod->exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &mod->exts));
             break;
 
         default:
@@ -4227,13 +4232,13 @@
  * @brief Parse submodule substatements.
  *
  * @param[in] ctx yang parser context for logging.
- * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in,out] in Input structure.
  * @param[out] submod Parsed submodule structure.
  *
  * @return LY_ERR values.
  */
 LY_ERR
-parse_submodule(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_submodule *submod)
+parse_submodule(struct lys_yang_parser_ctx *ctx, struct ly_in *in, struct lysp_submodule *submod)
 {
     LY_ERR ret = 0;
     char *buf, *word;
@@ -4243,10 +4248,10 @@
     struct lysp_submodule *dup;
 
     /* submodule name */
-    LY_CHECK_RET(get_argument(ctx, data, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
+    LY_CHECK_RET(get_argument(ctx, in, Y_IDENTIF_ARG, NULL, &word, &buf, &word_len));
     INSERT_WORD(ctx, buf, submod->name, word, word_len);
 
-    YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret, goto checks) {
+    YANG_READ_SUBSTMT_FOR(ctx, in, kw, word, word_len, ret, goto checks) {
 
 #define CHECK_ORDER(SECTION) \
         if (mod_stmt > SECTION) {LOGVAL_PARSER(ctx, LY_VCODE_INORD, ly_stmt2str(kw), ly_stmt2str(prev_kw)); return LY_EVALID;}mod_stmt = SECTION
@@ -4307,38 +4312,38 @@
         switch (kw) {
         /* module header */
         case LY_STMT_YANG_VERSION:
-            LY_CHECK_RET(parse_yangversion(ctx, data, &submod->version, &submod->exts));
+            LY_CHECK_RET(parse_yangversion(ctx, in, &submod->version, &submod->exts));
             ctx->mod_version = submod->version;
             break;
         case LY_STMT_BELONGS_TO:
-            LY_CHECK_RET(parse_belongsto(ctx, data, &submod->belongsto, &submod->prefix, &submod->exts));
+            LY_CHECK_RET(parse_belongsto(ctx, in, &submod->belongsto, &submod->prefix, &submod->exts));
             break;
 
         /* linkage */
         case LY_STMT_INCLUDE:
-            LY_CHECK_RET(parse_include(ctx, submod->name, data, &submod->includes));
+            LY_CHECK_RET(parse_include(ctx, submod->name, in, &submod->includes));
             break;
         case LY_STMT_IMPORT:
-            LY_CHECK_RET(parse_import(ctx, submod->prefix, data, &submod->imports));
+            LY_CHECK_RET(parse_import(ctx, submod->prefix, in, &submod->imports));
             break;
 
         /* meta */
         case LY_STMT_ORGANIZATION:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_ORGANIZATION, 0, &submod->org, Y_STR_ARG, &submod->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_ORGANIZATION, 0, &submod->org, Y_STR_ARG, &submod->exts));
             break;
         case LY_STMT_CONTACT:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_CONTACT, 0, &submod->contact, Y_STR_ARG, &submod->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_CONTACT, 0, &submod->contact, Y_STR_ARG, &submod->exts));
             break;
         case LY_STMT_DESCRIPTION:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &submod->dsc, Y_STR_ARG, &submod->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_DESCRIPTION, 0, &submod->dsc, Y_STR_ARG, &submod->exts));
             break;
         case LY_STMT_REFERENCE:
-            LY_CHECK_RET(parse_text_field(ctx, data, LYEXT_SUBSTMT_REFERENCE, 0, &submod->ref, Y_STR_ARG, &submod->exts));
+            LY_CHECK_RET(parse_text_field(ctx, in, LYEXT_SUBSTMT_REFERENCE, 0, &submod->ref, Y_STR_ARG, &submod->exts));
             break;
 
         /* revision */
         case LY_STMT_REVISION:
-            LY_CHECK_RET(parse_revision(ctx, data, &submod->revs));
+            LY_CHECK_RET(parse_revision(ctx, in, &submod->revs));
             break;
 
         /* body */
@@ -4346,56 +4351,56 @@
             PARSER_CHECK_STMTVER2_RET(ctx, "anydata", "submodule");
             /* fall through */
         case LY_STMT_ANYXML:
-            LY_CHECK_RET(parse_any(ctx, data, kw, NULL, &submod->data));
+            LY_CHECK_RET(parse_any(ctx, in, kw, NULL, &submod->data));
             break;
         case LY_STMT_CHOICE:
-            LY_CHECK_RET(parse_choice(ctx, data, NULL, &submod->data));
+            LY_CHECK_RET(parse_choice(ctx, in, NULL, &submod->data));
             break;
         case LY_STMT_CONTAINER:
-            LY_CHECK_RET(parse_container(ctx, data, NULL, &submod->data));
+            LY_CHECK_RET(parse_container(ctx, in, NULL, &submod->data));
             break;
         case LY_STMT_LEAF:
-            LY_CHECK_RET(parse_leaf(ctx, data, NULL, &submod->data));
+            LY_CHECK_RET(parse_leaf(ctx, in, NULL, &submod->data));
             break;
         case LY_STMT_LEAF_LIST:
-            LY_CHECK_RET(parse_leaflist(ctx, data, NULL, &submod->data));
+            LY_CHECK_RET(parse_leaflist(ctx, in, NULL, &submod->data));
             break;
         case LY_STMT_LIST:
-            LY_CHECK_RET(parse_list(ctx, data, NULL, &submod->data));
+            LY_CHECK_RET(parse_list(ctx, in, NULL, &submod->data));
             break;
         case LY_STMT_USES:
-            LY_CHECK_RET(parse_uses(ctx, data, NULL, &submod->data));
+            LY_CHECK_RET(parse_uses(ctx, in, NULL, &submod->data));
             break;
 
         case LY_STMT_AUGMENT:
-            LY_CHECK_RET(parse_augment(ctx, data, NULL, &submod->augments));
+            LY_CHECK_RET(parse_augment(ctx, in, NULL, &submod->augments));
             break;
         case LY_STMT_DEVIATION:
-            LY_CHECK_RET(parse_deviation(ctx, data, &submod->deviations));
+            LY_CHECK_RET(parse_deviation(ctx, in, &submod->deviations));
             break;
         case LY_STMT_EXTENSION:
-            LY_CHECK_RET(parse_extension(ctx, data, &submod->extensions));
+            LY_CHECK_RET(parse_extension(ctx, in, &submod->extensions));
             break;
         case LY_STMT_FEATURE:
-            LY_CHECK_RET(parse_feature(ctx, data, &submod->features));
+            LY_CHECK_RET(parse_feature(ctx, in, &submod->features));
             break;
         case LY_STMT_GROUPING:
-            LY_CHECK_RET(parse_grouping(ctx, data, NULL, &submod->groupings));
+            LY_CHECK_RET(parse_grouping(ctx, in, NULL, &submod->groupings));
             break;
         case LY_STMT_IDENTITY:
-            LY_CHECK_RET(parse_identity(ctx, data, &submod->identities));
+            LY_CHECK_RET(parse_identity(ctx, in, &submod->identities));
             break;
         case LY_STMT_NOTIFICATION:
-            LY_CHECK_RET(parse_notif(ctx, data, NULL, &submod->notifs));
+            LY_CHECK_RET(parse_notif(ctx, in, NULL, &submod->notifs));
             break;
         case LY_STMT_RPC:
-            LY_CHECK_RET(parse_action(ctx, data, NULL, &submod->rpcs));
+            LY_CHECK_RET(parse_action(ctx, in, NULL, &submod->rpcs));
             break;
         case LY_STMT_TYPEDEF:
-            LY_CHECK_RET(parse_typedef(ctx, NULL, data, &submod->typedefs));
+            LY_CHECK_RET(parse_typedef(ctx, NULL, in, &submod->typedefs));
             break;
         case LY_STMT_EXTENSION_INSTANCE:
-            LY_CHECK_RET(parse_ext(ctx, data, word, word_len, LYEXT_SUBSTMT_SELF, 0, &submod->exts));
+            LY_CHECK_RET(parse_ext(ctx, in, word, word_len, LYEXT_SUBSTMT_SELF, 0, &submod->exts));
             break;
 
         default:
@@ -4429,7 +4434,7 @@
 
 LY_ERR
 yang_parse_submodule(struct lys_yang_parser_ctx **context, struct ly_ctx *ly_ctx, struct lys_parser_ctx *main_ctx,
-                     const char *data, struct lysp_submodule **submod)
+                     struct ly_in *in, struct lysp_submodule **submod)
 {
     LY_ERR ret = LY_SUCCESS;
     char *word;
@@ -4450,7 +4455,7 @@
     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, in, &kw, &word, &word_len);
     LY_CHECK_GOTO(ret, cleanup);
 
     if (kw == LY_STMT_MODULE) {
@@ -4468,15 +4473,15 @@
     mod_p->parsing = 1;
 
     /* substatements */
-    ret = parse_submodule(*context, &data, mod_p);
+    ret = parse_submodule(*context, in, mod_p);
     LY_CHECK_GOTO(ret, cleanup);
 
     /* read some trailing spaces or new lines */
-    while(*data && isspace(*data)) {
-        data++;
+    while (isspace(in->current[0])) {
+        ++in->current;
     }
-    if (*data) {
-        LOGVAL_PARSER(*context, LY_VCODE_TRAILING_SUBMOD, 15, data, strlen(data) > 15 ? "..." : "");
+    if (in->current[0]) {
+        LOGVAL_PARSER(*context, LY_VCODE_TRAILING_SUBMOD, 15, in->current, strlen(in->current) > 15 ? "..." : "");
         ret = LY_EVALID;
         goto cleanup;
     }
@@ -4495,7 +4500,7 @@
 }
 
 LY_ERR
-yang_parse_module(struct lys_yang_parser_ctx **context, const char *data, struct lys_module *mod)
+yang_parse_module(struct lys_yang_parser_ctx **context, struct ly_in *in, struct lys_module *mod)
 {
     LY_ERR ret = LY_SUCCESS;
     char *word;
@@ -4512,7 +4517,7 @@
     (*context)->line = 1;
 
     /* "module"/"submodule" */
-    ret = get_keyword(*context, &data, &kw, &word, &word_len);
+    ret = get_keyword(*context, in, &kw, &word, &word_len);
     LY_CHECK_GOTO(ret, cleanup);
 
     if (kw == LY_STMT_SUBMODULE) {
@@ -4531,15 +4536,15 @@
     mod_p->parsing = 1;
 
     /* substatements */
-    ret = parse_module(*context, &data, mod_p);
+    ret = parse_module(*context, in, mod_p);
     LY_CHECK_GOTO(ret, cleanup);
 
     /* read some trailing spaces or new lines */
-    while(*data && isspace(*data)) {
-        data++;
+    while (isspace(in->current[0])) {
+        ++in->current;
     }
-    if (*data) {
-        LOGVAL_PARSER(*context, LY_VCODE_TRAILING_MOD, 15, data, strlen(data) > 15 ? "..." : "");
+    if (in->current[0]) {
+        LOGVAL_PARSER(*context, LY_VCODE_TRAILING_MOD, 15, in->current, strlen(in->current) > 15 ? "..." : "");
         ret = LY_EVALID;
         goto cleanup;
     }