From 034c1b1da5e979f5770b15bfd6341ceae734706a Mon Sep 17 00:00:00 2001 From: Derval Guillaume <gderval@uliege.be> Date: Sat, 3 Dec 2022 23:18:11 +0100 Subject: [PATCH] tags --- src/gboml/ast/constraints.py | 8 ++++--- src/gboml/ast/hyperedges.py | 12 ++++++---- src/gboml/ast/nodes.py | 32 ++++++++++++++------------ src/gboml/ast/objectives.py | 5 ++-- src/gboml/ast/variables.py | 6 +++-- src/gboml/gboml.lark | 23 ++++++++++-------- src/gboml/parsing.py | 21 +++++++++-------- tests/instances/ok/complex_parsing.txt | 4 +++- 8 files changed, 65 insertions(+), 46 deletions(-) diff --git a/src/gboml/ast/constraints.py b/src/gboml/ast/constraints.py index 38ffc1f..17cc19c 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 2f89464..ddd2097 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 3b6a7d7..2b452b3 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 5420e36..c78f5ee 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 f9fe0af..fd761ce 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 33149d6..9cad864 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 376053b..1612dcc 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 2259377..a617270 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] -- GitLab