Skip to content

Commit

Permalink
Update parsing of lists of keyword entries
Browse files Browse the repository at this point in the history
  • Loading branch information
gerlero committed Nov 25, 2024
1 parent 1580b4b commit bc810e4
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 31 deletions.
6 changes: 3 additions & 3 deletions foamlib/_files/_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@
Entry,
Field,
File,
MutableData,
MutableEntry,
)
from ._util import is_sequence


class FoamFile(
MutableMapping[
Optional[Union[str, Tuple[str, ...]]],
MutableData,
MutableEntry,
],
FoamFileIO,
):
Expand All @@ -49,7 +49,7 @@ class FoamFile(
DimensionSet = DimensionSet

class SubDict(
MutableMapping[str, MutableData],
MutableMapping[str, MutableEntry],
):
"""An OpenFOAM dictionary within a file as a mutable mapping."""

Expand Down
29 changes: 13 additions & 16 deletions foamlib/_files/_parsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,9 @@ def _keyword_entry_of(

subdict <<= Dict(Group(keyword_entry)[...], asdict=not located)

if not located:
return keyword_entry.copy().set_parse_action(lambda tks: tuple(tks))

return keyword_entry


Expand Down Expand Up @@ -231,35 +234,29 @@ def _keyword_entry_of(
)
)
)
_TOKEN = dbl_quoted_string | _IDENTIFIER
TOKEN = dbl_quoted_string | _IDENTIFIER
DATA = Forward()
KEYWORD = (
_TOKEN
| _list_of(_IDENTIFIER)
.set_parse_action(lambda tks: "(" + " ".join(tks[0]) + ")")
.ignore(_COMMENT)
.parse_with_tabs()
)
_KEYWORD_ENTRY = Dict(Group(_keyword_entry_of(KEYWORD, DATA)), asdict=True)
_KEYWORD_ENTRY = _keyword_entry_of(TOKEN | _list_of(_IDENTIFIER), DATA)
_DATA_ENTRY = Forward()
_LIST_ENTRY = _KEYWORD_ENTRY | _DATA_ENTRY
_LIST = _list_of(_LIST_ENTRY)
_NUMBER = common.signed_integer ^ common.ieee_float
_DATA_ENTRY <<= _FIELD | _LIST | _DIMENSIONED | _DIMENSIONS | _NUMBER | _SWITCH | _TOKEN
_DATA_ENTRY <<= _FIELD | _LIST | _DIMENSIONED | _DIMENSIONS | _NUMBER | _SWITCH | TOKEN

DATA <<= (
_DATA_ENTRY[1, ...]
.set_parse_action(lambda tks: tuple(tks) if len(tks) > 1 else [tks[0]])
.set_parse_action(lambda tks: [tuple(tks)] if len(tks) > 1 else [tks[0]])
.ignore(_COMMENT)
.parse_with_tabs()
)

_LOCATED_DICTIONARY = Group(
_keyword_entry_of(TOKEN, Opt(DATA, default=""), located=True)
)[...]
_LOCATED_DATA = Group(Located(DATA.copy().add_parse_action(lambda tks: ["", tks[0]])))

_FILE = (
Dict(
Group(_keyword_entry_of(KEYWORD, Opt(DATA, default=""), located=True))[...]
+ Opt(Group(Located(DATA.copy().add_parse_action(lambda tks: ["", tks[0]]))))
+ Group(_keyword_entry_of(KEYWORD, Opt(DATA, default=""), located=True))[...]
)
Dict(_LOCATED_DICTIONARY + Opt(_LOCATED_DATA) + _LOCATED_DICTIONARY)
.ignore(_COMMENT)
.ignore(Literal("#include") + ... + LineEnd()) # type: ignore [no-untyped-call]
.parse_with_tabs()
Expand Down
11 changes: 6 additions & 5 deletions foamlib/_files/_serialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
else:
from typing import Mapping, Sequence

from ._parsing import DATA, KEYWORD
from ._parsing import DATA, TOKEN
from ._types import Data, Dimensioned, DimensionSet, Entry
from ._util import is_sequence

Expand Down Expand Up @@ -60,9 +60,6 @@ def normalize(data: Entry, *, kind: Kind = Kind.DEFAULT) -> Entry:
return DimensionSet(*data)

if is_sequence(data) and (kind == Kind.SINGLE_ENTRY or not isinstance(data, tuple)):
if len(data) == 1 and isinstance(data[0], Mapping) and len(data[0]) > 1:
return [normalize({k: v}) for k, v in data[0].items()]

return [normalize(d, kind=Kind.SINGLE_ENTRY) for d in data]

if isinstance(data, Dimensioned):
Expand All @@ -72,7 +69,7 @@ def normalize(data: Entry, *, kind: Kind = Kind.DEFAULT) -> Entry:

if isinstance(data, str):
if kind == Kind.KEYWORD:
data = KEYWORD.parse_string(data, parse_all=True)[0]
data = TOKEN.parse_string(data, parse_all=True)[0]
assert isinstance(data, str)
return data

Expand Down Expand Up @@ -110,6 +107,10 @@ def dumps(

return b" ".join(entries)

if isinstance(data, tuple) and kind == Kind.SINGLE_ENTRY and len(data) == 2:
k, v = data
return dumps({k: v})

if isinstance(data, DimensionSet):
return b"[" + b" ".join(dumps(v) for v in data) + b"]"

Expand Down
4 changes: 2 additions & 2 deletions foamlib/_files/_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ def __post_init__(self) -> None:
A value that can be stored in an OpenFOAM file.
"""

MutableData = Union[
MutableEntry = Union[
Data,
MutableMapping[str, "MutableData"],
MutableMapping[str, "MutableEntry"],
]

Dict_ = Dict[str, Union["Entry", "Dict_"]]
Expand Down
10 changes: 5 additions & 5 deletions tests/test_files/test_parsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,16 +63,16 @@ def test_parse_value() -> None:
"simpleGrading",
[1, 1, 1],
)
assert Parsed(b"(a b; c d;)")[()] == [{"a": "b"}, {"c": "d"}]
assert Parsed(b"(a b; c d;)")[()] == [("a", "b"), ("c", "d")]
assert Parsed(b"(a {b c;} d {e g;})")[()] == [
{"a": {"b": "c"}},
{"d": {"e": "g"}},
("a", {"b": "c"}),
("d", {"e": "g"}),
]
assert Parsed(b"(a (0 1 2); b {})")[()] == [{"a": [0, 1, 2]}, {"b": {}}]
assert Parsed(b"(a (0 1 2); b {})")[()] == [("a", [0, 1, 2]), ("b", {})]
assert Parsed(b"(water oil mercury air)")[()] == ["water", "oil", "mercury", "air"]
assert Parsed(b"div(phi,U)")[()] == "div(phi,U)"
assert Parsed(b"((air and water) { type constant; sigma 0.07; })")[()] == [
{"(air and water)": {"type": "constant", "sigma": 0.07}}
(["air", "and", "water"], {"type": "constant", "sigma": 0.07})
]
assert Parsed(b"[]")[()] == FoamFile.DimensionSet()
assert Parsed(b"object f.1;")[("object",)] == "f.1"

0 comments on commit bc810e4

Please sign in to comment.