Skip to content

Commit 5d7762c

Browse files
committed
Further PR feedback
1 parent abdbc7a commit 5d7762c

File tree

2 files changed

+52
-38
lines changed

2 files changed

+52
-38
lines changed

gemd/units/impl.py

+43-30
Original file line numberDiff line numberDiff line change
@@ -40,40 +40,53 @@ def _scaling_find_blocks(token_stream: Generator[TokenInfo, Any, None]) -> List[
4040
multiplicative subunits of the original expression.
4141
4242
"""
43+
def _handle_operator(token_, exponent_context_, operator_stack_, result_):
44+
if token_.string not in _ALLOWED_OPERATORS:
45+
raise UndefinedUnitError(f"Unrecognized operator: {token_.string}")
46+
47+
# Figure out what level to append at
48+
if exponent_context_ or token_.string in {"**", "^", ".", "-", "+"}:
49+
# Exponents & unaries do not change context
50+
result_[-1].append(token_)
51+
else:
52+
result_.append([])
53+
54+
# Manage the operator stack
55+
if token_.string == '(':
56+
operator_stack_.append(token_)
57+
elif token_.string == ')':
58+
while operator_stack_: # don't worry about enforcing balance
59+
if operator_stack_.pop().string == '(':
60+
break # We found token's friend
61+
elif token_.string in {"**", "^"}:
62+
# A spare to pop so next loop is in exponent context
63+
operator_stack_.extend([token_] * 2)
64+
65+
def _handle_name(token_, exponent_context_, operator_stack_, result_):
66+
if exponent_context_ or len(result_[-1]) == 0 or result_[-1][-1].type != NAME:
67+
result_[-1].append(token_)
68+
else: # Break blocks for two units in a row
69+
result_.append([token_])
70+
71+
def _just_append(token_, exponent_context_, operator_stack_, result_):
72+
result_[-1].append(token_)
73+
74+
def _do_nothing(token_, exponent_context_, operator_stack_, result_):
75+
pass
76+
77+
dispatch = {
78+
OP: _handle_operator,
79+
NAME: _handle_name,
80+
NUMBER: _just_append,
81+
ERRORTOKEN: _just_append,
82+
}
83+
4384
result = [[]]
4485
operator_stack = []
4586
for token in token_stream:
4687
exponent_context = any(t.string in {"**", "^"} for t in operator_stack)
47-
if token.type == OP:
48-
if token.string not in _ALLOWED_OPERATORS:
49-
raise UndefinedUnitError(f"Unrecognized operator: {token.string}")
50-
51-
if exponent_context or token.string in {"**", "^", ".", "-", "+"}:
52-
# Exponents & unaries do not change context
53-
result[-1].append(token)
54-
elif token.string not in {}:
55-
result.append([])
56-
57-
if token.string == '(':
58-
operator_stack.append(token)
59-
elif token.string == ')':
60-
while operator_stack: # don't worry about enforcing balance
61-
if operator_stack.pop().string == '(':
62-
break # We found token's friend
63-
elif token.string in {"**", "^"}:
64-
operator_stack.append(token)
65-
continue # Break flow since next token is in exponent context
66-
elif token.type == NAME:
67-
if exponent_context or len(result[-1]) == 0 or result[-1][-1].type != NAME:
68-
result[-1].append(token)
69-
else: # Break blocks for two units in a row
70-
result.append([token])
71-
elif token.type == NUMBER:
72-
result[-1].append(token)
73-
elif token.type == ERRORTOKEN: # Keep non-legal Python symbols like °
74-
result[-1].append(token)
75-
# Drop other tokens, such as EOF
76-
88+
method = dispatch.get(token.type, _do_nothing)
89+
method(token, exponent_context, operator_stack, result)
7790
if len(operator_stack) > 0 and operator_stack[-1].string in {"**", "^"}:
7891
operator_stack.pop() # Exit context for this exponential
7992

tests/units/test_parser.py

+9-8
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,15 @@ def test_parse_expected(return_unit):
3737
assert parsed == parse_units(parsed, return_unit=return_unit)
3838
assert parse_units("") == 'dimensionless'
3939
# Scaling factors bind tightly to trailing units
40-
assert parse_units("g / 2.5 cm", return_unit=return_unit) == \
41-
parse_units("g / (2.5 cm)", return_unit=return_unit)
42-
assert parse_units("g / 2.5cm", return_unit=return_unit) == \
43-
parse_units("g / (2.5 cm)", return_unit=return_unit)
44-
assert parse_units("g / 25.mm", return_unit=return_unit) == \
45-
parse_units("g / (25. mm)", return_unit=return_unit)
46-
assert parse_units("g / 2.5 * cm", return_unit=return_unit) == \
47-
parse_units("g cm / 2.5", return_unit=return_unit)
40+
scaling = [
41+
("g / 2.5 cm", "g / (2.5 cm)"),
42+
("g / 2.5cm", "g / (2.5 cm)"),
43+
("g / 25.mm", "g / (25. mm)"),
44+
("g / 2.5 * cm", "g cm / 2.5")
45+
]
46+
for left, right in scaling:
47+
assert parse_units(left, return_unit=return_unit) == \
48+
parse_units(right, return_unit=return_unit)
4849

4950

5051
def test_parse_unexpected():

0 commit comments

Comments
 (0)