Skip to content

Commit 3405a20

Browse files
committed
utils: refactored parser
1 parent 87083fe commit 3405a20

21 files changed

Lines changed: 201 additions & 219 deletions

File tree

files/inp/valid_33.inp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ phys:e 2j 1 $ Turn off Brems.
2121
sdef par=p pos=-5 3 3 erg=2
2222
fir5 -5 0 0 0 1 0 0 1 1 1
2323
FS5 -10 9i 10
24-
CS5 -10 9i 10
24+
c CS5 -10 9i 10
2525
c f16:e (1<1[0:0 -2:2 -2:2]<3)
2626
c f26:e (2<2[0:0 -2:2 -2:2]<4)
2727
f8:e 1

src/pymcnp/Inp.py

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
from . import _file
66
from . import types
77
from . import errors
8-
from .utils import _parser
98

109

1110
class Inp(_file.File):
@@ -64,7 +63,7 @@ def from_mcnp(source: str):
6463
InpError: SYNTAX_FILE.
6564
"""
6665

67-
source, comments = _parser.preprocess_inp(source)
66+
source = Inp._preprocess(source)
6867
tokens = Inp._REGEX.match(source)
6968

7069
if not tokens:
@@ -160,6 +159,37 @@ def draw(self) -> _show.Shape:
160159

161160
return None
162161

162+
@staticmethod
163+
def _preprocess(source: str):
164+
"""
165+
Preprocess INP for ``from_mcnp``.
166+
167+
Parameters:
168+
source: INP to preprocess.
169+
"""
170+
171+
tokens = re.split(r'\n(#(?: \S+)+\n(?: *\d\S*(?: +\S+)+\n)+)', source)
172+
173+
source = ''
174+
for token in tokens:
175+
if match := re.match(r'#((?: \S+)+)\n((?: *\d\S*(?: +\S+)+\n)+)', token):
176+
cards = re.split(r'\s+', match[1])[1:]
177+
rows = [[card] for card in cards]
178+
179+
lines = match[2].split('\n')[:-1]
180+
for line in lines:
181+
parameters = re.split(r'\s+', line)
182+
for parameter, row in zip(parameters, rows):
183+
row.append(parameter)
184+
185+
source += '\n' + '\n'.join([' '.join(row) for row in rows]) + '\n'
186+
else:
187+
source += token
188+
189+
source = re.sub(r'\n +|& *\n *', ' ', source)
190+
191+
return source
192+
163193
@property
164194
def title(self) -> types.Integer:
165195
"""

src/pymcnp/inp/Cell.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
from . import _card
55
from .. import types
66
from .. import errors
7-
from ..utils import _parser
87

98

109
class Cell(_card.Card):
@@ -59,8 +58,7 @@ def to_mcnp(self):
5958
"""
6059

6160
source = f'{self.number} {self.material} {self.density if self.density is not None else ""} {self.geometry} {self.options if self.options is not None else ""}'
62-
source, comments = _parser.preprocess_inp(source)
63-
source = _parser.postprocess_inp(source)
61+
source = _card.Card._postprocess(source)
6462

6563
return source
6664

src/pymcnp/inp/Comment.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
from . import _card
44
from .. import types
5-
from ..utils import _parser
65

76

87
class Comment(_card.Card):
@@ -12,9 +11,9 @@ class Comment(_card.Card):
1211

1312
_ATTRS = {'text': types.String}
1413

15-
_REGEX = re.compile(r'c(.*)', re.IGNORECASE)
14+
_REGEX = re.compile(r'c(?: (.*))?', re.IGNORECASE)
1615

17-
def __init__(self, text: types.String):
16+
def __init__(self, text: types.String = None):
1817
"""
1918
Initializes ``Comment``.
2019
@@ -35,9 +34,8 @@ def to_mcnp(self):
3534
INP comment card.
3635
"""
3736

38-
source = f'c {self.text}'
39-
source, comments = _parser.preprocess_inp(source)
40-
source = _parser.postprocess_inp(source)
37+
source = f'c{f" {self.text}" if self.text else ""}'
38+
source = _card.Card._postprocess(source)
4139

4240
return source
4341

src/pymcnp/inp/Data.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
from . import _card
55
from .. import types
66
from .. import errors
7-
from ..utils import _parser
87

98

109
class Data(_card.Card):
@@ -38,8 +37,7 @@ def to_mcnp(self):
3837
"""
3938

4039
source = f'{self.option}'
41-
source, comments = _parser.preprocess_inp(source)
42-
source = _parser.postprocess_inp(source)
40+
source = _card.Card._postprocess(source)
4341

4442
return source
4543

src/pymcnp/inp/Like.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
from . import _card
55
from .. import types
66
from .. import errors
7-
from ..utils import _parser
87

98

109
class Like(_card.Card):
@@ -51,8 +50,7 @@ def to_mcnp(self):
5150
"""
5251

5352
source = f'{self.number} like {self.cell} but {self.options if self.options is not None else ""}'
54-
source, comments = _parser.preprocess_inp(source)
55-
source = _parser.postprocess_inp(source)
53+
source = _card.Card._postprocess(source)
5654

5755
return source
5856

src/pymcnp/inp/Surface.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
from .. import _show
77
from .. import types
88
from .. import errors
9-
from ..utils import _parser
109

1110

1211
class Surface(_card.Card):
@@ -60,8 +59,7 @@ def to_mcnp(self):
6059
"""
6160

6261
source = f'{self.prefix if self.prefix is not None else ""}{self.number} {self.transform if self.transform is not None else ""} {self.option}'
63-
source, comments = _parser.preprocess_inp(source)
64-
source = _parser.postprocess_inp(source)
62+
source = _card.Card._postprocess(source)
6563

6664
return source
6765

src/pymcnp/inp/_card.py

Lines changed: 73 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1+
import re
2+
3+
from . import _symbol
14
from .. import errors
2-
from .. import _symbol
3-
from ..utils import _parser
45

56

6-
class Card(_symbol.Nonterminal):
7+
class Card(_symbol.InpNonterminal):
78
"""
89
Represents generic INP cards.
910
"""
@@ -25,7 +26,7 @@ def from_mcnp(cls, source: str):
2526
InpError: SYNTAX_OPTION.
2627
"""
2728

28-
source, comments = _parser.preprocess_inp(source)
29+
source, comments = cls._preprocess(source)
2930
tokens = cls._REGEX.match(source)
3031

3132
if not tokens:
@@ -38,3 +39,71 @@ def from_mcnp(cls, source: str):
3839
card = cls(**attrs)
3940
card.comments = comments
4041
return card
42+
43+
@staticmethod
44+
def _preprocess(source: str) -> tuple[str, tuple[str]]:
45+
"""
46+
Preprocess INP for ``from_mcnp``.
47+
48+
Parameters:
49+
source: INP to preprocess.
50+
51+
Returns:
52+
Preprocess INP.
53+
"""
54+
55+
lines = []
56+
comments = []
57+
58+
for line in source.split('\n'):
59+
split = line.split('$', maxsplit=1)
60+
61+
if len(split) == 2:
62+
lines.append(split[0])
63+
comments.append(split[1])
64+
else:
65+
lines.append(line)
66+
67+
source = '\n'.join(lines)
68+
source = re.sub(r'\n +|& *\n *', ' ', source)
69+
source = re.sub(r' +', ' ', source)
70+
source = re.sub(r'[(] ', '(', source)
71+
source = re.sub(r' [)]', ')', source)
72+
source = re.sub(r'\n \n', '\n\n', source)
73+
source = re.sub(r' = | =|= |=', ' ', source)
74+
source = re.sub(r'\t', ' ', source)
75+
source = source.strip()
76+
77+
source = re.sub(r'((?: [jJ]){2,})(\s|\Z|\n)', lambda match: f' {len(match[1].strip().split())}j' + match[2], source)
78+
source = re.sub(r'((?: [rR]){2,})(\s|\Z|\n)', lambda match: f' {len(match[1].strip().split())}r' + match[2], source)
79+
source = re.sub(r'((?: [iI]){2,})(\s|\Z|\n)', lambda match: f' {len(match[1].strip().split())}i' + match[2], source)
80+
source = re.sub(r' (\d+)[jJ](\s|\Z|\n)', lambda match: int(match[1]) * ' j' + match[2], source)
81+
source = re.sub(r' (\d+)[rR](\s|\Z|\n)', lambda match: int(match[1]) * ' r' + match[2], source)
82+
source = re.sub(r' (\d+)[iI](\s|\Z|\n)', lambda match: int(match[1]) * ' I' + match[2], source)
83+
84+
return source, comments
85+
86+
@staticmethod
87+
def _postprocess(source: str) -> str:
88+
"""
89+
Postprocesses INP for ``to_mcnp``.
90+
91+
Parameters:
92+
source: INP to postprocess.
93+
94+
Returns:
95+
Postprocessed INP.
96+
"""
97+
98+
lines = []
99+
length = 0
100+
101+
for word in source.split(' '):
102+
if len(word) + length > 78:
103+
lines.append('&\n ')
104+
length = 5
105+
106+
lines.append(word)
107+
length += len(word) + 1
108+
109+
return ' '.join(lines)

src/pymcnp/inp/_entry.py

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1+
from . import _symbol
12
from .. import errors
2-
from .. import _symbol
3-
from ..utils import _parser
43

54

6-
class Entry(_symbol.Nonterminal):
5+
class Entry(_symbol.InpNonterminal):
76
"""
87
Represents generic INP entries.
98
"""
@@ -26,8 +25,7 @@ def from_mcnp(cls, source: str):
2625
InpError: SYNTAX_OPTION.
2726
"""
2827

29-
source, comments = _parser.preprocess_inp(source)
30-
28+
source = cls._preprocess(source)
3129
subclasses = cls.__subclasses__() or [cls]
3230

3331
for subclass in subclasses:
@@ -58,7 +56,4 @@ def to_mcnp(self):
5856
value.append(attribute)
5957
value = ' '.join(map(str, value))
6058

61-
source, comments = _parser.preprocess_inp(value)
62-
source = _parser.postprocess_inp(source)
63-
64-
return source
59+
return value

src/pymcnp/inp/_option.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1+
from . import _symbol
12
from .. import errors
2-
from .. import _symbol
3-
from ..utils import _parser
43

54

6-
class Option(_symbol.Nonterminal):
5+
class Option(_symbol.InpNonterminal):
76
"""
87
Represents generic INP options.
98
"""
@@ -26,8 +25,7 @@ def from_mcnp(cls, source: str):
2625
InpError: SYNTAX_OPTION.
2726
"""
2827

29-
source, comments = _parser.preprocess_inp(source)
30-
28+
source = Option._preprocess(source)
3129
subclasses = cls.__subclasses__() or [cls]
3230

3331
for subclass in subclasses:
@@ -59,7 +57,5 @@ def to_mcnp(self):
5957
value = ' '.join(map(str, value))
6058

6159
source = f"{self.prefix if hasattr(self, 'prefix') and self.prefix is not None else ''}{self._KEYWORD}{self.suffix if hasattr(self, 'suffix') and self.suffix is not None else ''}{(f':{self.designator}' if self.designator else '') if hasattr(self, 'designator') else ''} {value}"
62-
source, comments = _parser.preprocess_inp(source)
63-
source = _parser.postprocess_inp(source)
6460

6561
return source

0 commit comments

Comments
 (0)