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