yang - add range statement
diff --git a/src/parser_yang.c b/src/parser_yang.c
index bc3d834..a8529da 100644
--- a/src/parser_yang.c
+++ b/src/parser_yang.c
@@ -229,6 +229,9 @@
         case PATTERN_KEYWORD:
             ret = yang_check_string(module, &((struct lys_restr *) node)->dsc, "description", "pattern", value, line);
             break;
+        case RANGE_KEYWORD:
+            ret = yang_check_string(module, &((struct lys_restr *) node)->dsc, "description", "range", value, line);
+            break;
         }
     }
     return ret;
@@ -288,6 +291,9 @@
         case PATTERN_KEYWORD:
             ret = yang_check_string(module, &((struct lys_restr *) node)->ref, "reference", "pattern", value, line);
             break;
+        case RANGE_KEYWORD:
+            ret = yang_check_string(module, &((struct lys_restr *) node)->ref, "reference", "range", value, line);
+            break;
         }
     }
     return ret;
@@ -529,6 +535,9 @@
     case PATTERN_KEYWORD:
         exp = "pattern";
         break;
+    case RANGE_KEYWORD:
+        exp = "range";
+        break;
     }
     if (message==ERROR_APP_TAG_KEYWORD) {
         ret = yang_check_string(module, &save->eapptag, "error_app_tag", exp, value, line);
@@ -880,12 +889,7 @@
         if (typ->type->base == LY_TYPE_BINARY) {
             if (typ->type->info.str.pat_count) {
                 LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Binary type could not include pattern statement.");
-
-                /* clean patterns */
-                for (i = 0; i < typ->type->info.str.pat_count; ++i) {
-                    lys_restr_free(module->ctx, &(typ->type->info.str.patterns[i]));
-                }
-                free(typ->type->info.str.patterns);
+                typ->type->base = base;
                 goto error;
             }
             typ->type->info.binary.length = typ->type->info.str.length;
@@ -898,7 +902,33 @@
                 LOGVAL(LYE_INARG, typ->line, LY_VLOG_NONE, NULL, typ->type->info.str.length->expr, "length");
                 goto error;
             }
+        } else {
+            LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", parent->name);
+            goto error;
         }
+        break;
+    case LY_TYPE_DEC64:
+        if (typ->type->base == LY_TYPE_DEC64) {
+            if (lyp_check_length_range(typ->type->info.dec64.range->expr, typ->type)) {
+                LOGVAL(LYE_INARG, typ->line, LY_VLOG_NONE, NULL, typ->type->info.dec64.range->expr, "range");
+                goto error;
+            }
+        } else if (typ->type->base >= LY_TYPE_INT8 && typ->type->base <=LY_TYPE_UINT64) {
+            if (typ->type->info.dec64.dig) {
+                LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Numerical type could not include fraction statement.");
+                typ->type->base = base;
+                goto error;
+            }
+            typ->type->info.num.range = typ->type->info.dec64.range;
+            if (lyp_check_length_range(typ->type->info.num.range->expr, typ->type)) {
+                LOGVAL(LYE_INARG, typ->line, LY_VLOG_NONE, NULL, typ->type->info.num.range->expr, "range");
+                goto error;
+            }
+        } else {
+            LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", parent->name);
+            goto error;
+        }
+        break;
     }
     return EXIT_SUCCESS;
 
@@ -995,3 +1025,28 @@
     typ->type->info.str.pat_count++;
     return &typ->type->info.str.patterns[typ->type->info.str.pat_count-1];
 }
+
+void *
+yang_read_range(struct  lys_module *module, struct yang_type *typ, char *value, int line)
+{
+    if (typ->type->base != 0 && typ->type->base != LY_TYPE_DEC64) {
+        LOGVAL(LYE_SPEC, line, LY_VLOG_NONE, NULL, "Unexpected range statement.");
+        goto error;
+    }
+    typ->type->base = LY_TYPE_DEC64;
+    if (typ->type->info.dec64.range) {
+        LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, "range", "type");
+        goto error;
+    }
+    typ->type->info.dec64.range = calloc(1, sizeof *typ->type->info.dec64.range);
+    if (!typ->type->info.dec64.range) {
+        LOGMEM;
+        goto error;
+    }
+    typ->type->info.dec64.range->expr = lydict_insert_zc(module->ctx, value);
+    return typ->type->info.dec64.range;
+
+error:
+    free(value);
+    return NULL;
+}