diff --git a/src/gboml/ast/constraints.py b/src/gboml/ast/constraints.py
index 38ffc1fa95e8ea1e543c5c2f3cb4ead0545a121a..17cc19c3dcb86f79e019099f6a412ca7fdf796ae 100644
--- a/src/gboml/ast/constraints.py
+++ b/src/gboml/ast/constraints.py
@@ -1,4 +1,4 @@
-from dataclasses import dataclass
+from dataclasses import dataclass, field
 from enum import Enum
 from typing import Optional
 
@@ -24,11 +24,13 @@ class StdConstraint(Constraint):
     lhs: Expression
     op: Operator
     rhs: Expression
-    loop: Optional[Loop]
+    loop: Optional[Loop] = None
+    tags: list[str] = field(default_factory=list)
 
 
 @dataclass
 class SOSConstraint(Constraint):
     type: SOSType
     content: Array
-    loop: Optional[Loop]
+    loop: Optional[Loop] = None
+    tags: list[str] = field(default_factory=list)
diff --git a/src/gboml/ast/hyperedges.py b/src/gboml/ast/hyperedges.py
index 2f894647f133f53da9f6c542b08eb0c206592a4d..ddd209717cd161e25007ee77f7956a84e4993978 100644
--- a/src/gboml/ast/hyperedges.py
+++ b/src/gboml/ast/hyperedges.py
@@ -1,4 +1,4 @@
-from dataclasses import dataclass
+from dataclasses import dataclass, field
 
 from gboml.ast import Loop
 from gboml.ast.base import GBOMLObject
@@ -15,16 +15,18 @@ class HyperEdge(GBOMLObject):
 @dataclass
 class HyperEdgeDefinition(HyperEdge):
     name: str
-    parameters: list[Definition]
-    constraints: list[Constraint]
+    parameters: list[Definition] = field(default_factory=list)
+    constraints: list[Constraint] = field(default_factory=list)
+    tags: list[str] = field(default_factory=list)
 
 
 @dataclass
 class HyperEdgeGenerator(HyperEdge):
     name: VarOrParam
     loop: Loop
-    parameters: list[Definition]
-    constraints: list[Constraint]
+    parameters: list[Definition] = field(default_factory=list)
+    constraints: list[Constraint] = field(default_factory=list)
+    tags: list[str] = field(default_factory=list)
 
 
 @dataclass
diff --git a/src/gboml/ast/nodes.py b/src/gboml/ast/nodes.py
index 3b6a7d7cac40174e80fbfd4cc46692d29b9664c6..2b452b35e05bfcd596b562cd5a1cfa4cfb3427f8 100644
--- a/src/gboml/ast/nodes.py
+++ b/src/gboml/ast/nodes.py
@@ -1,4 +1,4 @@
-from dataclasses import dataclass
+from dataclasses import dataclass, field
 
 from gboml.ast import Loop
 from gboml.ast.base import GBOMLObject
@@ -17,24 +17,26 @@ class Node(GBOMLObject):
 @dataclass
 class NodeDefinition(Node):
     name: str
-    parameters: list[Definition]
-    nodes: list[Node]
-    hyperedges: list[HyperEdge]
-    variables: list[VariableDefinition]
-    constraints: list[Constraint]
-    objectives: list[Objective]
+    parameters: list[Definition] = field(default_factory=list)
+    nodes: list[Node] = field(default_factory=list)
+    hyperedges: list[HyperEdge] = field(default_factory=list)
+    variables: list[VariableDefinition] = field(default_factory=list)
+    constraints: list[Constraint] = field(default_factory=list)
+    objectives: list[Objective] = field(default_factory=list)
+    tags: list[str] = field(default_factory=list)
 
 
 @dataclass
 class NodeGenerator(Node):
     name: VarOrParam
     loop: Loop
-    parameters: list[Definition]
-    nodes: list[Node]
-    hyperedges: list[HyperEdge]
-    variables: list[VariableDefinition]
-    constraints: list[Constraint]
-    objectives: list[Objective]
+    parameters: list[Definition] = field(default_factory=list)
+    nodes: list[Node] = field(default_factory=list)
+    hyperedges: list[HyperEdge] = field(default_factory=list)
+    variables: list[VariableDefinition] = field(default_factory=list)
+    constraints: list[Constraint] = field(default_factory=list)
+    objectives: list[Objective] = field(default_factory=list)
+    tags: list[str] = field(default_factory=list)
 
 
 @dataclass
@@ -42,5 +44,5 @@ class NodeImport(Node):
     name: str
     imported_name: VarOrParam
     imported_from: str
-    scope_changes: list[ScopeChange]
-    redefinitions: list[Definition]
+    scope_changes: list[ScopeChange] = field(default_factory=list)
+    redefinitions: list[Definition] = field(default_factory=list)
diff --git a/src/gboml/ast/objectives.py b/src/gboml/ast/objectives.py
index 5420e365311fb10de2ecc0881c01148482b9a667..c78f5ee12b61262b3a07c66debb4b062a74fd2da 100644
--- a/src/gboml/ast/objectives.py
+++ b/src/gboml/ast/objectives.py
@@ -1,4 +1,4 @@
-from dataclasses import dataclass
+from dataclasses import dataclass, field
 from enum import Enum
 from typing import Optional
 
@@ -17,4 +17,5 @@ class Objective(GBOMLObject):
     type: ObjType
     name: Optional[str]
     expression: Expression
-    loop: Optional[Loop]
+    loop: Optional[Loop] = None
+    tags: list[str] = field(default_factory=list)
diff --git a/src/gboml/ast/variables.py b/src/gboml/ast/variables.py
index f9fe0af274bdd3a61554d8985fb3c5d55a65cd6d..fd761cee0896a06e73321b35ffec912d0fba40a2 100644
--- a/src/gboml/ast/variables.py
+++ b/src/gboml/ast/variables.py
@@ -1,4 +1,4 @@
-from dataclasses import dataclass
+from dataclasses import dataclass, field
 from enum import Enum
 from typing import Optional
 
@@ -22,6 +22,7 @@ class VarType(Enum):
 class Definition(GBOMLObject):
     name: str
     value: RValue
+    tags: list[str] = field(default_factory=list)
 
 
 @dataclass
@@ -29,7 +30,8 @@ class VariableDefinition(GBOMLObject):
     scope: VarScope
     type: VarType
     name: VarOrParam
-    import_from: Optional[VarOrParam]
+    import_from: Optional[VarOrParam] = None
+    tags: list[str] = field(default_factory=list)
 
 
 @dataclass
diff --git a/src/gboml/gboml.lark b/src/gboml/gboml.lark
index 33149d60704efdaa3baddd9899ac69c36ebd41f5..9cad8648b6498b1b2db67028377d1b0468fc6077 100644
--- a/src/gboml/gboml.lark
+++ b/src/gboml/gboml.lark
@@ -26,13 +26,18 @@ program_block: _program*
 global_block: _block_repeat_or_pass{"#GLOBAL",definition}?
 _program: node | hyperedge
 
+// TAGS
+tags: TAG*
+TAG: /@[a-zA-Z\-_]+/
+
 // NODES
 ?node: node_definition | node_import
 node_definition: _block_shortcut{_node_header, _node_content}
-_node_header: "#NODE" var_or_param [loop]
+_node_header: "#NODE" var_or_param [loop] tags
 _node_content: parameters_block program_block variables_block constraints_block objectives_block
 
-parameters_block: (_block_repeat_or_pass{"#PARAMETERS",definition})?
+parameters_block: (_block_repeat_or_pass{_opt_param_header,definition})?
+_opt_param_header: "#PARAMETERS"?
 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})?
@@ -46,27 +51,27 @@ variable_scope_change: ID SCOPE ";"
 ?hyperedge: hyperedge_definition | hyperedge_import
 
 hyperedge_definition: _block_shortcut{_hyperedge_header, _hyperedge_content}
-_hyperedge_header: "#HYPEREDGE" var_or_param [loop]
+_hyperedge_header: "#HYPEREDGE" var_or_param [loop] tags
 _hyperedge_content: parameters_block constraints_block
 
 hyperedge_import: "#HYPEREDGE" ID "=" "import" var_or_param "from" STRING hyperedge_redefs
 hyperedge_redefs: "with" definition* | ";"
 
 // VARIABLES
-variable_definition: SCOPE [VTYPE] ":" var_or_param [_LARROW var_or_param] ";"
+variable_definition: SCOPE [VTYPE] ":" var_or_param [_LARROW var_or_param] tags ";"
 SCOPE: "internal" | "external"
 VTYPE: "binary" | "continuous" | "integer"
 _LARROW.1: "<-"
 
 // CONSTRAINTS
 ?constraint: constraint_sos | constraint_std
-constraint_std: [ID ":"] expression CTR_OPERATOR expression [loop] ";"
+constraint_std: [ID ":"] expression CTR_OPERATOR expression [loop] tags ";"
 CTR_OPERATOR: "<=" | ">=" | "=="
-constraint_sos: [ID ":"] SOS_TYPE array [loop] ";"
+constraint_sos: [ID ":"] SOS_TYPE array [loop] tags ";"
 SOS_TYPE.1: "SOS1" | "SOS2"
 
 // OBJECTIVES
-objective: OBJ_TYPE [ID] ":" expression [loop] ";"
+objective: OBJ_TYPE [ID] ":" expression [loop] tags ";"
 OBJ_TYPE: "min" | "max"
 
 // LOOPS
@@ -86,7 +91,7 @@ bool_expression_comparison: expression (COMPARISON_OPERATOR | CTR_OPERATOR) expr
 COMPARISON_OPERATOR:  "<" | ">" | "!="
 
 // DEFINITIONS
-definition: ID "=" rvalue ";"
+definition: ID "=" rvalue tags ";"
 
 // ARRAYS
 array_or_dict: "{" separated_maybe_empty_list{_array_or_dict_entry, ","} "}"
@@ -115,7 +120,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 plist{index}
+var_or_param_leaf: (ID | TAG) plist{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 376053be2ca9a355f5cdfdd9160fcf2e222c44cd..1612dcce28e2397f3b2ad3cdd470e886564e7283 100644
--- a/src/gboml/parsing.py
+++ b/src/gboml/parsing.py
@@ -53,7 +53,8 @@ def _lark_to_gboml(tree: Tree, filename: Optional[str] = None) -> GBOMLGraph:
         as_list = {
             "objectives_block", "constraints_block", "variables_block",
             "parameters_block", "global_block", "plist", "node_redefs",
-            "hyperedge_redefs", "separated_list", "separated_maybe_empty_list"
+            "hyperedge_redefs", "separated_list", "separated_maybe_empty_list",
+            "tags"
         }
 
         #
@@ -105,6 +106,7 @@ def _lark_to_gboml(tree: Tree, filename: Optional[str] = None) -> GBOMLGraph:
         def INT(self, token): return int(token.value)
         def FLOAT(self, token): return float(token.value)
         def ID(self, token): return token.value
+        def TAG(self, token): return token.value
         def SCOPE(self, token): return VarScope(token.value)
         def SOS_TYPE(self, token): return SOSType(token.value)
         def CTR_OPERATOR(self, token): return Operator(token.value)
@@ -118,7 +120,7 @@ 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],
+        def hyperedge_definition(self, meta: Meta, name: VarOrParam, loop: Optional[Loop], tags: list[str],
                                  param_block: list[Definition] = None, constraint_block: list[Constraint] = None):
             if constraint_block is None:
                 constraint_block = []
@@ -128,11 +130,11 @@ def _lark_to_gboml(tree: Tree, filename: Optional[str] = None) -> GBOMLGraph:
             if loop is None:
                 if len(name.path) != 1 or len(name.path[0].indices) != 0:
                     raise Exception(f"Invalid name for node: {name}")
-                return HyperEdgeDefinition(name.path[0].name, param_block, constraint_block, meta=meta)
+                return HyperEdgeDefinition(name.path[0].name, param_block, constraint_block, tags, meta=meta)
             else:
-                return HyperEdgeGenerator(name, loop, param_block, constraint_block, meta=meta)
+                return HyperEdgeGenerator(name, loop, param_block, constraint_block, tags, meta=meta)
 
-        def node_definition(self, meta: Meta, name: VarOrParam, loop: Optional[Loop],
+        def node_definition(self, meta: Meta, name: VarOrParam, loop: Optional[Loop], tags: list[str],
                             param_block: list[Definition] = None, subprogram_block: NodesAndHyperEdges = None,
                             variable_block: list[VariableDefinition] = None, constraint_block: list[Constraint] = None,
                             objectives_block: list[Objective] = None):
@@ -154,13 +156,13 @@ def _lark_to_gboml(tree: Tree, filename: Optional[str] = None) -> GBOMLGraph:
                                       param_block,
                                       subprogram_block.nodes, subprogram_block.hyperedges,
                                       variable_block, constraint_block,
-                                      objectives_block, meta=meta)
+                                      objectives_block, tags, meta=meta)
             else:
                 return NodeGenerator(name, loop,
                                      param_block,
                                      subprogram_block.nodes, subprogram_block.hyperedges,
                                      variable_block, constraint_block,
-                                     objectives_block, meta=meta)
+                                     objectives_block, tags, meta=meta)
 
         def node_import(self, meta: Meta, name: str, imported_name: VarOrParam, imported_from: str, redef: list[ScopeChange | Definition]):
             return NodeImport(name, imported_name, imported_from,
@@ -170,8 +172,9 @@ 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]):
-            return VariableDefinition(scope, type or VarType.continuous, name, import_from, 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 multi_loop(self, meta: Meta, *loops: Tuple[Loop]):
             return MultiLoop(list(loops), meta=meta)
diff --git a/tests/instances/ok/complex_parsing.txt b/tests/instances/ok/complex_parsing.txt
index 2259377171f49e43423bc1d57edbee618f22e67c..a617270feb59b665283e8ae5b382cad8cdbe7bd7 100644
--- a/tests/instances/ok/complex_parsing.txt
+++ b/tests/instances/ok/complex_parsing.txt
@@ -13,7 +13,9 @@
     a = 2;
     b external;
     c internal;
-#NODE nodeL[i] for i in [0:10]
+#NODE nodeL[i] for i in [0:10] @hello
+    x = 3;
+    x = @test @test;
     #VARIABLES
         pass;
 #HYPEREDGE E[i] for i in [0:10]