diff --git a/src/gboml/gboml.lark b/src/gboml/gboml.lark
index a5864f761f72ba0895a873e80e096c426dd23463..33149d60704efdaa3baddd9899ac69c36ebd41f5 100644
--- a/src/gboml/gboml.lark
+++ b/src/gboml/gboml.lark
@@ -15,27 +15,27 @@ 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*
+_block_repeat_or_pass{name, content}: name (_PASS ";" | content+)
+_block_shortcut{name, content}: name (_PASS? ";" | content)
+_PASS.1: "pass"
 
 // HEADER
 start: [time_horizon] global_block program_block
 program_block: _program*
 ?time_horizon: "#TIMEHORIZON" "T" "=" INT ";"
-global_block: ("#GLOBAL" definition*)?
+global_block: _block_repeat_or_pass{"#GLOBAL",definition}?
 _program: node | hyperedge
 
 // NODES
 ?node: node_definition | node_import
-node_definition: "#NODE" var_or_param [loop] \
-                  parameters_block \
-                  program_block \
-                  variables_block \
-                  constraints_block \
-                  objectives_block
-
-parameters_block: ("#PARAMETERS" definition*)?
-variables_block: "#VARIABLES" variable_definition*
-constraints_block: ("#CONSTRAINTS" constraint*)?
-objectives_block: ("#OBJECTIVES" objective*)?
+node_definition: _block_shortcut{_node_header, _node_content}
+_node_header: "#NODE" var_or_param [loop]
+_node_content: parameters_block program_block variables_block constraints_block objectives_block
+
+parameters_block: (_block_repeat_or_pass{"#PARAMETERS",definition})?
+variables_block: _block_repeat_or_pass{"#VARIABLES",variable_definition}
+constraints_block: (_block_repeat_or_pass{"#CONSTRAINTS",constraint})?
+objectives_block: (_block_repeat_or_pass{"#OBJECTIVES",objective})?
 
 node_import: "#NODE" ID "=" "import" var_or_param "from" STRING node_redefs
 node_redefs: ("with" redefinition*) | ";"
@@ -45,9 +45,9 @@ variable_scope_change: ID SCOPE ";"
 // HYPEREDGES
 ?hyperedge: hyperedge_definition | hyperedge_import
 
-hyperedge_definition: "#HYPEREDGE" var_or_param [loop] \
-                      parameters_block \
-                      constraints_block
+hyperedge_definition: _block_shortcut{_hyperedge_header, _hyperedge_content}
+_hyperedge_header: "#HYPEREDGE" var_or_param [loop]
+_hyperedge_content: parameters_block constraints_block
 
 hyperedge_import: "#HYPEREDGE" ID "=" "import" var_or_param "from" STRING hyperedge_redefs
 hyperedge_redefs: "with" definition* | ";"
diff --git a/src/gboml/parsing.py b/src/gboml/parsing.py
index 83fd7cfde1e75ecaf0bec656ca0dd45ab20c3e76..376053be2ca9a355f5cdfdd9160fcf2e222c44cd 100644
--- a/src/gboml/parsing.py
+++ b/src/gboml/parsing.py
@@ -118,7 +118,13 @@ def _lark_to_gboml(tree: Tree, filename: Optional[str] = None) -> GBOMLGraph:
         def program_block(self, meta: Meta, *childrens: list[Node | HyperEdge]) -> NodesAndHyperEdges:
             return self.NodesAndHyperEdges([x for x in childrens if isinstance(x, Node)], [x for x in childrens if isinstance(x, HyperEdge)])
 
-        def hyperedge_definition(self, meta: Meta, name: VarOrParam, loop: Optional[Loop], param_block: list[Definition], constraint_block: list[Constraint]):
+        def hyperedge_definition(self, meta: Meta, name: VarOrParam, loop: Optional[Loop],
+                                 param_block: list[Definition] = None, constraint_block: list[Constraint] = None):
+            if constraint_block is None:
+                constraint_block = []
+            if param_block is None:
+                param_block = []
+
             if loop is None:
                 if len(name.path) != 1 or len(name.path[0].indices) != 0:
                     raise Exception(f"Invalid name for node: {name}")
@@ -126,9 +132,21 @@ def _lark_to_gboml(tree: Tree, filename: Optional[str] = None) -> GBOMLGraph:
             else:
                 return HyperEdgeGenerator(name, loop, param_block, constraint_block, meta=meta)
 
-        def node_definition(self, meta: Meta, name: VarOrParam, loop: Optional[Loop], param_block: list[Definition], subprogram_block: NodesAndHyperEdges,
-                            variable_block: list[VariableDefinition], constraint_block: list[Constraint],
-                            objectives_block: list[Objective]):
+        def node_definition(self, meta: Meta, name: VarOrParam, loop: Optional[Loop],
+                            param_block: list[Definition] = None, subprogram_block: NodesAndHyperEdges = None,
+                            variable_block: list[VariableDefinition] = None, constraint_block: list[Constraint] = None,
+                            objectives_block: list[Objective] = None):
+            if objectives_block is None:
+                objectives_block = []
+            if constraint_block is None:
+                constraint_block = []
+            if variable_block is None:
+                variable_block = []
+            if param_block is None:
+                param_block = []
+            if subprogram_block is None:
+                subprogram_block = self.NodesAndHyperEdges([], [])
+
             if loop is None:
                 if len(name.path) != 1 or len(name.path[0].indices) != 0:
                     raise Exception(f"Invalid name for node: {name}")
diff --git a/tests/instances/ko_parsing/wrong_global.txt b/tests/instances/ko_parsing/wrong_global.txt
new file mode 100644
index 0000000000000000000000000000000000000000..67d6345587bfcaf6066a4d9349263e53a0ffbe15
--- /dev/null
+++ b/tests/instances/ko_parsing/wrong_global.txt
@@ -0,0 +1,5 @@
+#GLOBAL
+
+#NODE x
+    #VARIABLES
+        internal: a;
\ No newline at end of file
diff --git a/tests/instances/ok/complex_parsing.txt b/tests/instances/ok/complex_parsing.txt
index fed325b24bd164514610fae54de247fe052065b1..2259377171f49e43423bc1d57edbee618f22e67c 100644
--- a/tests/instances/ok/complex_parsing.txt
+++ b/tests/instances/ok/complex_parsing.txt
@@ -15,8 +15,10 @@
     c internal;
 #NODE nodeL[i] for i in [0:10]
     #VARIABLES
+        pass;
 #HYPEREDGE E[i] for i in [0:10]
     #CONSTRAINTS
+        pass;
 #NODE node1
     #PARAMETERS
         a = 2;
diff --git a/tests/instances/ok/good_global.txt b/tests/instances/ok/good_global.txt
new file mode 100644
index 0000000000000000000000000000000000000000..559373b5bef43df51beadbdf520b447bcbd7ae02
--- /dev/null
+++ b/tests/instances/ok/good_global.txt
@@ -0,0 +1,16 @@
+#GLOBAL
+    pass;
+
+#NODE x
+    #VARIABLES
+        internal: a;
+
+#NODE y
+    pass;
+
+#NODE z;
+
+#HYPEREDGE e;
+
+#HYPEREDGE e2
+    pass;
\ No newline at end of file