tests CHANGE cover get_keyword in YANG parser
diff --git a/src/parser_yang.c b/src/parser_yang.c
index ec5200a..77c7084 100644
--- a/src/parser_yang.c
+++ b/src/parser_yang.c
@@ -145,7 +145,11 @@
  * @param[in] ctx yang parser context for logging.
  * @param[in] c UTF8 code point of a character to check.
  * @param[in] first Flag to check the first character of an identifier, which is more restricted.
- * @param[in,out] prefix Storage for internally used flag in case of possible prefixed identifiers.
+ * @param[in,out] prefix Storage for internally used flag in case of possible prefixed identifiers:
+ * 0 - colon not yet found (no prefix)
+ * 1 - \p c is the colon character
+ * 2 - prefix already processed, now processing the identifier
+ *
  * If the identifier cannot be prefixed, NULL is expected.
  * @return LY_ERR values.
  */
@@ -653,8 +657,6 @@
     LY_ERR ret;
     int prefix;
     const char *word_start;
-    /* slash: 0 - nothing, 1 - last character was '/' */
-    int slash = 0;
     unsigned int c;
     size_t len;
 
@@ -665,32 +667,27 @@
 
     /* first skip "optsep", comments */
     while (**data) {
-        if (slash) {
-            if (**data == '/') {
+        switch (**data) {
+        case '/':
+            if ((*data)[1] == '/') {
                 /* one-line comment */
-                MOVE_INPUT(ctx, data, 1);
+                MOVE_INPUT(ctx, data, 2);
                 ret = skip_comment(ctx, data, 1);
                 if (ret) {
                     return ret;
                 }
-            } else if (**data == '*') {
+            } else if ((*data)[1] == '*') {
                 /* block comment */
-                MOVE_INPUT(ctx, data, 1);
+                MOVE_INPUT(ctx, data, 2);
                 ret = skip_comment(ctx, data, 2);
                 if (ret) {
                     return ret;
                 }
             } else {
-                /* not a comment after all */
-                goto keyword_start;
+                /* error - not a comment after all, keyword cannot start with slash */
+                LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Invalid identifier first character '/'.");
+                return LY_EVALID;
             }
-            slash = 0;
-        }
-
-        switch (**data) {
-        case '/':
-            slash = 1;
-            ++ctx->indent;
             break;
         case '\n':
             /* skip whitespaces (optsep) */
@@ -910,6 +907,12 @@
         case '\t':
             /* mandatory "sep" */
             break;
+        case '{':
+            /* allowed only for input and output statements which can be without arguments */
+            if (*kw == YANG_INPUT || *kw == YANG_OUTPUT) {
+                break;
+            }
+            /* fallthrough */
         default:
             MOVE_INPUT(ctx, data, 1);
             LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start,
@@ -932,7 +935,7 @@
         }
 
         /* prefix is mandatory for extension instances */
-        if (prefix != 1) {
+        if (prefix != 2) {
             LOGVAL_YANG(ctx, LY_VCODE_INSTREXP, (int)(*data - word_start), word_start, "a keyword");
             return LY_EVALID;
         }
diff --git a/tests/src/test_parser_yang.c b/tests/src/test_parser_yang.c
index 87b847c..60ba4ad 100644
--- a/tests/src/test_parser_yang.c
+++ b/tests/src/test_parser_yang.c
@@ -131,8 +131,13 @@
     assert_int_equal(0, prefix);
     assert_int_equal(LY_SUCCESS, check_identifierchar(&ctx, ':', 0, &prefix));
     assert_int_equal(1, prefix);
+    assert_int_equal(LY_EVALID, check_identifierchar(&ctx, ':', 0, &prefix));
+    assert_int_equal(1, prefix);
     assert_int_equal(LY_SUCCESS, check_identifierchar(&ctx, 'b', 0, &prefix));
     assert_int_equal(2, prefix);
+    /* second colon is invalid */
+    assert_int_equal(LY_EVALID, check_identifierchar(&ctx, ':', 0, &prefix));
+    logbuf_assert("Invalid identifier character ':'. Line number 1.");
 }
 
 static void
@@ -293,6 +298,327 @@
     str = ";";
     assert_int_equal(LY_EVALID, get_argument(&ctx, &str, Y_STR_ARG, &word, &buf, &len));
     logbuf_assert("Invalid character sequence \";\", expected an argument. Line number 7.");
+}
+
+static void
+test_stmts(void **state)
+{
+    (void) state; /* unused */
+
+    struct ly_parser_ctx ctx;
+    const char *str, *p;
+    enum yang_keyword kw;
+    char *word;
+    size_t len;
+
+    ctx.ctx = NULL;
+    ctx.line = 1;
+
+    str = "\n// comment\n\tinput\t{";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_INPUT, kw);
+    assert_int_equal(5, len);
+    assert_string_equal("input\t{", word);
+    assert_string_equal("\t{", str);
+
+    str = "\t /* comment */\t output\n\t{";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_OUTPUT, kw);
+    assert_int_equal(6, len);
+    assert_string_equal("output\n\t{", word);
+    assert_string_equal("\n\t{", str);
+
+    str = "/input { "; /* invalid slash */
+    assert_int_equal(LY_EVALID, get_keyword(&ctx, &str, &kw, &word, &len));
+    logbuf_assert("Invalid identifier first character '/'. Line number 4.");
+
+    str = "not-a-statement-nor-extension { "; /* invalid identifier */
+    assert_int_equal(LY_EVALID, get_keyword(&ctx, &str, &kw, &word, &len));
+    logbuf_assert("Invalid character sequence \"not-a-statement-nor-extension\", expected a keyword. Line number 4.");
+
+    str = "path;"; /* missing sep after the keyword */
+    assert_int_equal(LY_EVALID, get_keyword(&ctx, &str, &kw, &word, &len));
+    logbuf_assert("Invalid character sequence \"path;\", expected a keyword followed by a separator. Line number 4.");
+
+    str = "action ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_ACTION, kw);
+    assert_int_equal(6, len);
+    str = "anydata ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_ANYDATA, kw);
+    assert_int_equal(7, len);
+    str = "anyxml ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_ANYXML, kw);
+    assert_int_equal(6, len);
+    str = "argument ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_ARGUMENT, kw);
+    assert_int_equal(8, len);
+    str = "augment ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_AUGMENT, kw);
+    assert_int_equal(7, len);
+    str = "base ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_BASE, kw);
+    assert_int_equal(4, len);
+    str = "belongs-to ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_BELONGS_TO, kw);
+    assert_int_equal(10, len);
+    str = "bit ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_BIT, kw);
+    assert_int_equal(3, len);
+    str = "case ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_CASE, kw);
+    assert_int_equal(4, len);
+    str = "choice ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_CHOICE, kw);
+    assert_int_equal(6, len);
+    str = "config ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_CONFIG, kw);
+    assert_int_equal(6, len);
+    str = "contact ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_CONTACT, kw);
+    assert_int_equal(7, len);
+    str = "container ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_CONTAINER, kw);
+    assert_int_equal(9, len);
+    str = "default ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_DEFAULT, kw);
+    assert_int_equal(7, len);
+    str = "description ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_DESCRIPTION, kw);
+    assert_int_equal(11, len);
+    str = "deviate ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_DEVIATE, kw);
+    assert_int_equal(7, len);
+    str = "deviation ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_DEVIATION, kw);
+    assert_int_equal(9, len);
+    str = "enum ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_ENUM, kw);
+    assert_int_equal(4, len);
+    str = "error-app-tag ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_ERROR_APP_TAG, kw);
+    assert_int_equal(13, len);
+    str = "error-message ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_ERROR_MESSAGE, kw);
+    assert_int_equal(13, len);
+    str = "extension ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_EXTENSION, kw);
+    assert_int_equal(9, len);
+    str = "feature ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_FEATURE, kw);
+    assert_int_equal(7, len);
+    str = "fraction-digits ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_FRACTION_DIGITS, kw);
+    assert_int_equal(15, len);
+    str = "grouping ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_GROUPING, kw);
+    assert_int_equal(8, len);
+    str = "identity ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_IDENTITY, kw);
+    assert_int_equal(8, len);
+    str = "if-feature ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_IF_FEATURE, kw);
+    assert_int_equal(10, len);
+    str = "import ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_IMPORT, kw);
+    assert_int_equal(6, len);
+    str = "include ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_INCLUDE, kw);
+    assert_int_equal(7, len);
+    str = "input{";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_INPUT, kw);
+    assert_int_equal(5, len);
+    str = "key ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_KEY, kw);
+    assert_int_equal(3, len);
+    str = "leaf ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_LEAF, kw);
+    assert_int_equal(4, len);
+    str = "leaf-list ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_LEAF_LIST, kw);
+    assert_int_equal(9, len);
+    str = "length ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_LENGTH, kw);
+    assert_int_equal(6, len);
+    str = "list ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_LIST, kw);
+    assert_int_equal(4, len);
+    str = "mandatory ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_MANDATORY, kw);
+    assert_int_equal(9, len);
+    str = "max-elements ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_MAX_ELEMENTS, kw);
+    assert_int_equal(12, len);
+    str = "min-elements ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_MIN_ELEMENTS, kw);
+    assert_int_equal(12, len);
+    str = "modifier ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_MODIFIER, kw);
+    assert_int_equal(8, len);
+    str = "module ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_MODULE, kw);
+    assert_int_equal(6, len);
+    str = "must ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_MUST, kw);
+    assert_int_equal(4, len);
+    str = "namespace ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_NAMESPACE, kw);
+    assert_int_equal(9, len);
+    str = "notification ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_NOTIFICATION, kw);
+    assert_int_equal(12, len);
+    str = "ordered-by ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_ORDERED_BY, kw);
+    assert_int_equal(10, len);
+    str = "organization ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_ORGANIZATION, kw);
+    assert_int_equal(12, len);
+    str = "output ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_OUTPUT, kw);
+    assert_int_equal(6, len);
+    str = "path ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_PATH, kw);
+    assert_int_equal(4, len);
+    str = "pattern ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_PATTERN, kw);
+    assert_int_equal(7, len);
+    str = "position ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_POSITION, kw);
+    assert_int_equal(8, len);
+    str = "prefix ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_PREFIX, kw);
+    assert_int_equal(6, len);
+    str = "presence ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_PRESENCE, kw);
+    assert_int_equal(8, len);
+    str = "range ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_RANGE, kw);
+    assert_int_equal(5, len);
+    str = "reference ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_REFERENCE, kw);
+    assert_int_equal(9, len);
+    str = "refine ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_REFINE, kw);
+    assert_int_equal(6, len);
+    str = "require-instance ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_REQUIRE_INSTANCE, kw);
+    assert_int_equal(16, len);
+    str = "revision ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_REVISION, kw);
+    assert_int_equal(8, len);
+    str = "revision-date ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_REVISION_DATE, kw);
+    assert_int_equal(13, len);
+    str = "rpc ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_RPC, kw);
+    assert_int_equal(3, len);
+    str = "status ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_STATUS, kw);
+    assert_int_equal(6, len);
+    str = "submodule ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_SUBMODULE, kw);
+    assert_int_equal(9, len);
+    str = "type ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_TYPE, kw);
+    assert_int_equal(4, len);
+    str = "typedef ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_TYPEDEF, kw);
+    assert_int_equal(7, len);
+    str = "unique ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_UNIQUE, kw);
+    assert_int_equal(6, len);
+    str = "units ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_UNITS, kw);
+    assert_int_equal(5, len);
+    str = "uses ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_USES, kw);
+    assert_int_equal(4, len);
+    str = "value ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_VALUE, kw);
+    assert_int_equal(5, len);
+    str = "when ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_WHEN, kw);
+    assert_int_equal(4, len);
+    str = "yang-version ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_YANG_VERSION, kw);
+    assert_int_equal(12, len);
+    str = "yin-element ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_YIN_ELEMENT, kw);
+    assert_int_equal(11, len);
+
+    /* geenric extension */
+    str = p = "nacm:default-deny-write;";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(YANG_CUSTOM, kw);
+    assert_int_equal(23, len);
+    assert_ptr_equal(p, word);
 
 }
 
@@ -302,6 +628,7 @@
         cmocka_unit_test_setup(test_helpers, logger_setup),
         cmocka_unit_test_setup(test_comments, logger_setup),
         cmocka_unit_test_setup(test_arg, logger_setup),
+        cmocka_unit_test_setup(test_stmts, logger_setup),
     };
 
     return cmocka_run_group_tests(tests, NULL, NULL);