diff --git a/src/gboml/ast/variables.py b/src/gboml/ast/variables.py
index 1ca9e80e6b63e442ea6f7fdf29255c5f83828b20..6a1f0942484777809560f6671c87ce02d017bbb7 100644
--- a/src/gboml/ast/variables.py
+++ b/src/gboml/ast/variables.py
@@ -2,6 +2,7 @@ from dataclasses import dataclass, field
 from enum import Enum
 from typing import Optional
 
+from gboml.ast.expressions import Expression
 from gboml.ast.functions import Function
 from gboml.ast.arrays import Array, Range
 from gboml.ast.base import GBOMLObject, NamedGBOMLObject
@@ -57,6 +58,8 @@ class VariableDefinition(NamedGBOMLObject):
     indices: list[str]
     scope: VarScope
     type: VarType
+    bound_lower: Optional[Expression]
+    bound_upper: Optional[Expression]
     import_from: Optional[VarOrParam] = None
     tags: set[str] = field(default_factory=set)
 
diff --git a/src/gboml/gboml.lark b/src/gboml/gboml.lark
index bf7ff85a91c2dbda265cd0e494197654f47bcede..a7e96bf14b26484f27fc4552f9524f1d0ce9615b 100644
--- a/src/gboml/gboml.lark
+++ b/src/gboml/gboml.lark
@@ -64,7 +64,7 @@ hyperedge_import: "#HYPEREDGE" ID "=" "import" var_or_param "from" STRING hypere
 hyperedge_redefs: "with" definition* | ";"
 
 // VARIABLES
-variable_definition: SCOPE [VTYPE] ":" separated_list{variable_name,","} [_LARROW separated_list{var_or_param, ","}] tags ";"
+variable_definition: SCOPE [VTYPE] ":" separated_list{variable_name,","} [_LARROW separated_list{var_or_param, ","}] ["in" "[" [expression] ":" [expression] "]"] tags ";"
 variable_name: ID olist{index}
 SCOPE: "internal" | "external"
 VTYPE: "binary" | "continuous" | "integer"
diff --git a/src/gboml/parsing.py b/src/gboml/parsing.py
index 0d1f0dfd3b007d22a75f953f2e4d0b4236a83cf3..ab703ade6363ba6b8aa9510e5d5d59f1200a1fcf 100644
--- a/src/gboml/parsing.py
+++ b/src/gboml/parsing.py
@@ -193,12 +193,14 @@ def _lark_to_gboml(tree: Tree, filename: Optional[str] = None) -> GBOMLGraph:
             return GBOMLGraph(time_horizon, global_defs, nodes_hyperedges.nodes, nodes_hyperedges.hyperedges, meta=meta)
 
         def variable_definition(self, meta: Meta, scope: VarScope, type: Optional[VarType], names: list[(str, list[str])],
-                                imports_from: Optional[list[VarOrParam]], tags: set[str]):
+                                imports_from: Optional[list[VarOrParam]],
+                                bound_lower: Optional[Expression], bound_upper: Optional[Expression], tags: set[str]):
             if imports_from is not None and len(imports_from) != len(names):
                 raise Exception("Invalid variable import, numbers of variables on the left and on the right-side of "
                                 "`<-` don't match")
             for name, import_from in zip(names, imports_from or repeat(None, len(names))):
-                yield VariableDefinition(name[0], name[1], scope, type or VarType.continuous, import_from, tags, meta=meta)
+                yield VariableDefinition(name[0], name[1], scope, type or VarType.continuous,
+                                         bound_lower, bound_upper, import_from, tags, meta=meta)
 
         def variables_block(self, _: Meta, *defs: Tuple[Iterable[VariableDefinition]]):
             return [vd for iterable in defs for vd in iterable]
@@ -223,5 +225,4 @@ def _lark_to_gboml(tree: Tree, filename: Optional[str] = None) -> GBOMLGraph:
             else:
                 return ConstantDefinition(name, val, tags, meta=meta)
 
-
     return GBOMLLarkTransformer().transform(tree)