Skip to content

Commit 34df4f4

Browse files
author
wpbonelli
committed
generalize!
1 parent 708ef9a commit 34df4f4

File tree

2 files changed

+45
-45
lines changed

2 files changed

+45
-45
lines changed

flopy4/mf6/codec/reader/transformer.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1+
from collections import ChainMap
2+
from collections.abc import Mapping
13
from pathlib import Path
24
from typing import Any
35

46
import numpy as np
57
import xarray as xr
68
from lark import Token, Transformer
9+
from modflow_devtools.dfn import _SCALAR_TYPES, Dfn, get_blocks, get_fields
710

811

912
class BasicTransformer(Transformer):
@@ -59,7 +62,16 @@ def INT(self, token: Token) -> int:
5962
class TypedTransformer(Transformer):
6063
"""Type-aware transformer for MF6 input files."""
6164

62-
def start(self, items: list[Any]) -> dict:
65+
def __init__(self, visit_tokens=True, dfn: Dfn = None):
66+
super().__init__(visit_tokens)
67+
self.dfn = dfn
68+
self.blocks = get_blocks(dfn) if dfn else None
69+
self.fields = get_fields(dfn) if dfn else None
70+
71+
def start(self, items: list[Any]) -> Mapping:
72+
return ChainMap(*items)
73+
74+
def block(self, items: list[Any]) -> dict:
6375
return items[0]
6476

6577
def array(self, items: list[Any]) -> dict:
@@ -157,3 +169,19 @@ def try_create_dataarray(array_info: dict) -> dict:
157169
case "external":
158170
pass
159171
return array_info
172+
173+
def __default__(self, data, children, meta):
174+
if self.blocks is None or self.fields is None:
175+
return super().__default__(data, children, meta)
176+
if data.endswith("_block") and (block_name := data[:-6]) in self.blocks:
177+
return {block_name: children[0]}
178+
elif data.endswith("_vars"):
179+
return {item[0].lower(): item[1] for item in children}
180+
elif (field := self.fields.get(data, None)) is not None:
181+
if field["type"] == "keyword":
182+
return data, True
183+
elif field["type"] in _SCALAR_TYPES and field.get("shape", None):
184+
return data, TypedTransformer.try_create_dataarray(children[0])
185+
else:
186+
return data, children[0]
187+
return super().__default__(data, children, meta)

test/test_parser.py

Lines changed: 16 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import os
2-
from collections import ChainMap
32
from pathlib import Path
4-
from typing import Any
53

64
import numpy as np
75
import xarray as xr
@@ -151,48 +149,22 @@ def test_transform_full_component():
151149
z: "z"i array
152150
"""
153151
parser = make_typed_parser(grammar)
154-
155-
class BlockTransformer(TypedTransformer):
156-
def start(self, items: list[Any]) -> dict:
157-
return ChainMap(*items)
158-
159-
def block(self, items: list[Any]) -> dict:
160-
return items[0]
161-
162-
def options_block(self, items: list[Any]) -> dict:
163-
return {"options": items[0]}
164-
165-
def arrays_block(self, items: list[Any]) -> dict:
166-
return {"arrays": items[0]}
167-
168-
def options_vars(self, items: list[Any]) -> dict:
169-
return {item[0].lower(): item[1] for item in items}
170-
171-
def arrays_vars(self, items: list[Any]) -> dict:
172-
return {item[0].lower(): item[1] for item in items}
173-
174-
def r2d2(self, _: list[Any]) -> bool:
175-
return "r2d2", True
176-
177-
def b(self, items: list[Any]) -> tuple[str, str]:
178-
return "b", items[0]
179-
180-
def c(self, items: list[Any]) -> tuple[str, int]:
181-
return "c", items[0]
182-
183-
def p(self, items: list[Any]) -> tuple[str, float]:
184-
return "p", items[0]
185-
186-
def x(self, items: list[Any]) -> tuple[str, dict]:
187-
return "x", TypedTransformer.try_create_dataarray(items[0])
188-
189-
def y(self, items: list[Any]) -> tuple[str, dict]:
190-
return "y", TypedTransformer.try_create_dataarray(items[0])
191-
192-
def z(self, items: list[Any]) -> tuple[str, dict]:
193-
return "z", TypedTransformer.try_create_dataarray(items[0])
194-
195-
transformer = BlockTransformer(visit_tokens=False)
152+
transformer = TypedTransformer(
153+
visit_tokens=False,
154+
dfn={
155+
"options": {
156+
"r2d2": {"name": "r2d2", "type": "keyword"},
157+
"b": {"name": "b", "type": "string"},
158+
"c": {"name": "c", "type": "integer"},
159+
"p": {"name": "p", "type": "double"},
160+
},
161+
"arrays": {
162+
"x": {"name": "x", "type": "double", "shape": None},
163+
"y": {"name": "y", "type": "array", "shape": None},
164+
"z": {"name": "z", "type": "array", "shape": None},
165+
},
166+
},
167+
)
196168
result = transformer.transform(
197169
parser.parse("""
198170
BEGIN OPTIONS

0 commit comments

Comments
 (0)