diff --git a/src/gboml/gboml.lark b/src/gboml/gboml.lark
index 9118012b1aebff0c4430d2ab4747ee514116078b..8938d67a13f0660f8d7cf442af3746b24d1e7139 100644
--- a/src/gboml/gboml.lark
+++ b/src/gboml/gboml.lark
@@ -14,7 +14,8 @@ _separated_list{sub, sep}: sub (sep sub)*
 separated_list{sub, sep}: _separated_list{sub, sep}
 _separated_maybe_empty_list{sub, sep}: _separated_list{sub, sep}?
 separated_maybe_empty_list{sub, sep}: _separated_list{sub, sep}?
-plist{content}: content*
+olist{content}: content* //optionnal list
+mlist{content}: content+ //mandatory list
 _block_repeat_or_pass{name, content}: name (_PASS ";" | content+)
 _block_shortcut{name, content}: name (_PASS? ";" | content)
 _PASS.1: "pass"
@@ -58,7 +59,7 @@ hyperedge_import: "#HYPEREDGE" ID "=" "import" var_or_param "from" STRING hypere
 hyperedge_redefs: "with" definition* | ";"
 
 // VARIABLES
-variable_definition: SCOPE [VTYPE] ":" var_or_param [_LARROW var_or_param] tags ";"
+variable_definition: SCOPE [VTYPE] ":" separated_list{var_or_param,","} [_LARROW separated_list{var_or_param, ","}] tags ";"
 SCOPE: "internal" | "external"
 VTYPE: "binary" | "continuous" | "integer"
 _LARROW.1: "<-"
@@ -121,7 +122,7 @@ function: ID "(" separated_maybe_empty_list{generated_rvalue, ","} ")"
 
 // VAR OR PARAM LINK
 var_or_param: separated_list{var_or_param_leaf, "."}
-var_or_param_leaf: (ID | TAG) plist{index}
+var_or_param_leaf: (ID | TAG) olist{index}
 ?index: "[" rvalue "]"
 
 //rvalue: anything that can be assigned to a parameter
diff --git a/src/gboml/parsing.py b/src/gboml/parsing.py
index 1aa31304166b66a46a41d5369873c5090bf7eac1..1421beeee8cc734890e17e11ad91b759cb6a9c71 100644
--- a/src/gboml/parsing.py
+++ b/src/gboml/parsing.py
@@ -1,8 +1,9 @@
 import pathlib
+from itertools import repeat
 
 from lark import Lark, Tree, Token, Transformer, v_args
 from gboml.ast import *
-from typing import Optional, Tuple
+from typing import Optional, Tuple, Iterable
 from collections import namedtuple
 
 parser = Lark(open((pathlib.Path(__file__).parent / "gboml.lark").resolve()).read(), start="start", parser="lalr")
@@ -51,8 +52,8 @@ def _lark_to_gboml(tree: Tree, filename: Optional[str] = None) -> GBOMLGraph:
         # These rules will be converted to lists
         #
         as_list = {
-            "objectives_block", "constraints_block", "variables_block",
-            "parameters_block", "global_block", "plist", "node_redefs",
+            "objectives_block", "constraints_block",
+            "parameters_block", "global_block", "olist", "mlist", "node_redefs",
             "hyperedge_redefs", "separated_list", "separated_maybe_empty_list",
             "tags"
         }
@@ -173,9 +174,16 @@ def _lark_to_gboml(tree: Tree, filename: Optional[str] = None) -> GBOMLGraph:
         def start(self, meta: Meta, time_horizon: Optional[int], global_defs: list[Definition], nodes_hyperedges: NodesAndHyperEdges):
             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], name: VarOrParam,
-                                import_from: Optional[VarOrParam], tags: list[str]):
-            return VariableDefinition(scope, type or VarType.continuous, name, import_from, tags, meta=meta)
+        def variable_definition(self, meta: Meta, scope: VarScope, type: Optional[VarType], names: list[VarOrParam],
+                                imports_from: Optional[list[VarOrParam]], tags: list[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(scope, type or VarType.continuous, name, import_from, tags, meta=meta)
+
+        def variables_block(self, _: Meta, *defs: list[Iterable[VariableDefinition]]):
+            return [vd for iterable in defs for vd in iterable]
 
         def multi_loop(self, meta: Meta, *loops: Tuple[Loop]):
             return MultiLoop(list(loops), meta=meta)
diff --git a/tests/instances/ok/multi_v_import.txt b/tests/instances/ok/multi_v_import.txt
new file mode 100644
index 0000000000000000000000000000000000000000..ee85f730e976fc8ade0dcdfd8b5c54d874b3dace
--- /dev/null
+++ b/tests/instances/ok/multi_v_import.txt
@@ -0,0 +1,15 @@
+// Working example where x = -4
+
+#TIMEHORIZON T = 1;
+
+#NODE P
+    #NODE C
+        #VARIABLES
+            internal: x;
+            internal: y;
+    #VARIABLES
+        internal : x, y <- C.x, C.y;
+    #CONSTRAINTS
+        x <= -4;
+    #OBJECTIVES
+        max : x;
\ No newline at end of file