|
44 | 44 | _SAB_RE = re.compile(r'\s*[Mm][Tt](\d+)((?:\s+\S+)+)') |
45 | 45 | _MODE_RE = re.compile(r'\s*mode(?:\s+\S+)*') |
46 | 46 | _COMPLEMENT_RE = re.compile(r'(#)[ ]*(\d+)') |
47 | | -_REPEAT_RE = re.compile(r'(\d+)\s+(\d+)[rR]') |
48 | 47 | _NUM_RE = re.compile(r'(\d)([+-])(\d)') |
49 | 48 |
|
| 49 | +_REPEAT_RE = re.compile(r""" |
| 50 | + (?P<value> # The numeric value to be repeated |
| 51 | + [+-]? # Optional sign |
| 52 | + (?: # Mantissa |
| 53 | + \d+(?:\.\d*)? # Digits with optional fractional part (e.g., 3 or 3. or 3.0) |
| 54 | + | # or |
| 55 | + \.\d+ # Leading-dot form (e.g., .25) |
| 56 | + ) |
| 57 | + (?: # Optional exponent |
| 58 | + [eEdD][+-]?\d+ # E/D exponent with optional sign (e.g., 1e-3, 2D+3) |
| 59 | + | # or MCNP "bare" exponent without E/D |
| 60 | + [+-]\d+ # appended sign+digits (e.g., 1.0-3 -> 1.0e-3) |
| 61 | + )? |
| 62 | + ) |
| 63 | + \s+ # One or more spaces between value and count |
| 64 | + (?P<count>\d+) # The repeat count |
| 65 | + [rR] # The 'R' or 'r' suffix |
| 66 | +""", re.VERBOSE) |
| 67 | + |
50 | 68 |
|
51 | 69 | def float_(val): |
52 | 70 | """Convert scientific notation literals that don't have an 'e' in them to float""" |
@@ -346,11 +364,11 @@ def sanitize(section: str) -> str: |
346 | 364 | section = re.sub('\n {5}', ' ', section) |
347 | 365 |
|
348 | 366 | # Expand repeated numbers |
349 | | - m = _REPEAT_RE.search(section) |
350 | | - while m is not None: |
351 | | - section = _REPEAT_RE.sub(' '.join((int(m.group(2)) + 1)*[m.group(1)]), |
352 | | - section, 1) |
353 | | - m = _REPEAT_RE.search(section) |
| 367 | + section = _REPEAT_RE.sub( |
| 368 | + lambda m: ' '.join([m.group('value')] * (int(m.group('count')) + 1)), |
| 369 | + section, |
| 370 | + ) |
| 371 | + |
354 | 372 | return section |
355 | 373 |
|
356 | 374 |
|
|
0 commit comments