parsers CHANGE clarify function names

- rename lys_parse_nodeid() to ly_parse_nodeid()
- rename lys_parse_instance_predicate() to ly_parse_instance_prediacte()
- both functions were moved into common.c

Both functions provide generic parsing functionality for different path
formats, not limited to schemas. Therefore they now have generic libyang
prefix instead of libyang schema prefix.
diff --git a/src/common.c b/src/common.c
index e34d42e..e658031 100644
--- a/src/common.c
+++ b/src/common.c
@@ -25,6 +25,7 @@
 
 #include "extensions.h"
 #include "tree_schema.h"
+#include "tree_schema_internal.h"
 
 const char *const ly_stmt_list[] = {
     [YANG_ACTION] = "action",
@@ -364,3 +365,156 @@
     *ret = u;
     return LY_SUCCESS;
 }
+
+/**
+ * @brief Parse an identifier.
+ *
+ * ;; An identifier MUST NOT start with (('X'|'x') ('M'|'m') ('L'|'l'))
+ * identifier          = (ALPHA / "_")
+ *                       *(ALPHA / DIGIT / "_" / "-" / ".")
+ *
+ * @param[in,out] id Identifier to parse. When returned, it points to the first character which is not part of the identifier.
+ * @return LY_ERR value: LY_SUCCESS or LY_EINVAL in case of invalid starting character.
+ */
+static LY_ERR
+lys_parse_id(const char **id)
+{
+    assert(id && *id);
+
+    if (!is_yangidentstartchar(**id)) {
+        return LY_EINVAL;
+    }
+    ++(*id);
+
+    while (is_yangidentchar(**id)) {
+        ++(*id);
+    }
+    return LY_SUCCESS;
+}
+
+LY_ERR
+ly_parse_nodeid(const char **id, const char **prefix, size_t *prefix_len, const char **name, size_t *name_len)
+{
+    assert(id && *id);
+    assert(prefix && prefix_len);
+    assert(name && name_len);
+
+    *prefix = *id;
+    *prefix_len = 0;
+    *name = NULL;
+    *name_len = 0;
+
+    LY_CHECK_RET(lys_parse_id(id));
+    if (**id == ':') {
+        /* there is prefix */
+        *prefix_len = *id - *prefix;
+        ++(*id);
+        *name = *id;
+
+        LY_CHECK_RET(lys_parse_id(id));
+        *name_len = *id - *name;
+    } else {
+        /* there is no prefix, so what we have as prefix now is actually the name */
+        *name = *prefix;
+        *name_len = *id - *name;
+        *prefix = NULL;
+    }
+
+    return LY_SUCCESS;
+}
+
+LY_ERR
+ly_parse_instance_predicate(const char **pred, size_t limit,
+                             const char **prefix, size_t *prefix_len, const char **id, size_t *id_len, const char **value, size_t *value_len,
+                             const char **errmsg)
+{
+    LY_ERR ret = LY_EVALID;
+    const char *in = *pred;
+    size_t offset = 1;
+    int expr = 0;
+    char quot;
+
+    assert(in[0] == '\[');
+
+    *prefix = *id = *value = NULL;
+    *prefix_len = *id_len = *value_len = 0;
+
+    /* leading *WSP */
+    for (; isspace(in[offset]); offset++);
+
+    if (isdigit(in[offset])) {
+        /* pos: "[" *WSP positive-integer-value *WSP "]" */
+        if (in[offset] == '0') {
+            /* zero */
+            *errmsg = "The position predicate cannot be zero.";
+            goto error;
+        }
+
+        /* positive-integer-value */
+        *id = &in[offset++];
+        for (; isdigit(in[offset]); offset++);
+        *id_len = &in[offset] - *id;
+
+    } else if (in[offset] == '.') {
+        /* leaf-list-predicate: "[" *WSP "." *WSP "=" *WSP quoted-string *WSP "]" */
+        *id = &in[offset];
+        *id_len = 1;
+        offset++;
+        expr = 1;
+
+    } else {
+        /* key-predicate: "[" *WSP node-identifier *WSP "=" *WSP quoted-string *WSP "]" */
+        in = &in[offset];
+        if (ly_parse_nodeid(&in, prefix, prefix_len, id, id_len)) {
+            *errmsg = "Invalid node-identifier.";
+            goto error;
+        }
+        offset = in - *pred;
+        in = *pred;
+        expr = 1;
+    }
+
+    if (expr) {
+        /*  *WSP "=" *WSP quoted-string *WSP "]" */
+        for (; isspace(in[offset]); offset++);
+
+        if (in[offset] != '=') {
+            *errmsg = "Unexpected character instead of \'=\'.";
+            goto error;
+        }
+        offset++;
+        for (; isspace(in[offset]); offset++);
+
+        /* quoted-string */
+        quot = in[offset++];
+        if (quot != '\'' && quot != '\"') {
+            *errmsg = "String value is not quoted.";
+            goto error;
+        }
+        *value = &in[offset];
+        for (;offset < limit && in[offset] != quot; offset++);
+        *value_len = &in[offset] - *value;
+    }
+
+    /* *WSP "]" */
+    for(; isspace(in[offset]); offset++);
+    if (in[offset] != ']') {
+        *errmsg = "Predicate is not terminated by \']\' character.";
+        goto error;
+    }
+
+    if (offset < limit) {
+        return LY_SUCCESS;
+    }
+
+    /* we read after the limit */
+    *errmsg = "Predicate is incomplete.";
+    *prefix = *id = *value = NULL;
+    *prefix_len = *id_len = *value_len = 0;
+    offset = limit;
+    ret = LY_EINVAL;
+
+error:
+    *pred = &in[offset];
+    return ret;
+}