-
Notifications
You must be signed in to change notification settings - Fork 1
/
parse.py
65 lines (52 loc) · 1.94 KB
/
parse.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
__all__ = ['Parse']
import functools as f
import typing as t
if t.TYPE_CHECKING:
from .core import Foam
from .type import Dict
class Parse:
'''OpenFOAM YAML parser'''
@classmethod
def from_foam(cls, _: 'Foam') -> 'Parse':
return cls()
def data(self, data: 'Dict') -> t.Iterator[str]:
for key, value in data.items():
yield f'{self.key(key)} {self.value(value)}'
def key(self, key: str) -> str:
key = key.replace(' ', '') # div(phi, U) -> div(phi,U)
if any(c in key for c in '()*'): # (U|k|epsilon) -> "(U|k|epsilon)"
key = f'"{key}"'
return key
@f.singledispatchmethod
def value(self, value: t.Any) -> str:
raise Exception(f'Unknown type "{type(value).__name__}"')
@value.register(bool)
def _(self, value: bool) -> str:
return f'{str(value).lower()};'
@value.register(str)
@value.register(int)
@value.register(float)
def _(self, value: t.Union[str, int, float]) -> str:
return f'{value};'
@value.register(list)
def _(self, value: t.List[t.Any]) -> str:
if not value or isinstance(value[0], (str, int, float)):
return f'({" ".join(map(str, value))});'
elif isinstance(value[0], dict):
strings = []
for element in value:
head = tuple(k for k, v in element.items() if v is None)
if head:
element.pop(head[0])
string = ' '.join(self.data(element))
strings.append(f'{head[0]} {{{string}}}')
else:
string = ' '.join(self.data(element))
strings.append(f'{{{string}}}')
return f'({" ".join(strings)});'
else:
raise Exception(f'Unknown list "{value}"')
@value.register(dict)
def _(self, value: 'Dict') -> str:
string = ' '.join(self.data(value))
return f'{{{string}}}'