Skip to content

Commit

Permalink
Fix zero remainder rules
Browse files Browse the repository at this point in the history
  • Loading branch information
synesthesiam committed Jul 10, 2024
1 parent f001027 commit 9b64edc
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 10 deletions.
3 changes: 3 additions & 0 deletions tests/test_en.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

def test_english():
engine = RbnfEngine.for_language("en")

assert engine.format_number(7) == "seven"
assert engine.format_number(15) == "fifteen"
assert engine.format_number(42) == "forty-two"
Expand Down Expand Up @@ -39,6 +40,8 @@ def test_english():
)

# Ordinals
assert engine.format_number(20, ruleset_name=RulesetName.ORDINAL) == "twentieth"
assert engine.format_number(30, ruleset_name=RulesetName.ORDINAL) == "thirtieth"
assert engine.format_number(99, ruleset_name=RulesetName.ORDINAL) == "ninety-ninth"
assert engine.format_number(11, ruleset_name=RulesetName.ORDINAL) == "eleventh"

Expand Down
4 changes: 2 additions & 2 deletions tests/test_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def test_parse_sub():
parts=[
SubRulePart(SubType.QUOTIENT),
TextRulePart(" hundred"),
SubRulePart(SubType.REMAINER, is_optional=True, text_before=" "),
SubRulePart(SubType.REMAINDER, is_optional=True, text_before=" "),
],
)

Expand All @@ -32,7 +32,7 @@ def test_parse_ruleset_name():
parts=[
SubRulePart(SubType.QUOTIENT, ruleset_name="spellout-cardinal-masculine"),
TextRulePart("­hundert"),
SubRulePart(SubType.REMAINER, is_optional=True, text_before="­"),
SubRulePart(SubType.REMAINDER, is_optional=True, text_before="­"),
],
)

Expand Down
2 changes: 1 addition & 1 deletion unicode_rbnf/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.1.0
1.2.0
22 changes: 15 additions & 7 deletions unicode_rbnf/engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class TextRulePart(RbnfRulePart):
class SubType(str, Enum):
"""Type of substitution."""

REMAINER = "remainder"
REMAINDER = "remainder"
"""Use remainder for rule value."""

QUOTIENT = "quotient"
Expand Down Expand Up @@ -91,7 +91,7 @@ class ParseState(str, Enum):
TEXT = "text"
SUB_OPTIONAL_BEFORE = "optional_before"
SUB_OPTIONAL_AFTER = "optional_after"
SUB_REMAINER = "remainder"
SUB_REMAINDER = "remainder"
SUB_QUOTIENT = "quotient"
SUB_RULESET_NAME = "sub_ruleset_name"
REPLACE_RULESET_NAME = "replace_ruleset_name"
Expand Down Expand Up @@ -164,15 +164,15 @@ def parse(value_str: str, text: str, radix: int = 10) -> "Optional[RbnfRule]":
if c in (">", "→"):
# Divide the number by the rule's divisor and format the remainder
if state in {ParseState.TEXT, ParseState.SUB_OPTIONAL_BEFORE}:
state = ParseState.SUB_REMAINER
state = ParseState.SUB_REMAINDER
part = SubRulePart(
SubType.REMAINER,
SubType.REMAINDER,
is_optional=is_sub_optional,
text_before=sub_text_before,
)
rule.parts.append(part)
sub_text_before = ""
elif state in {ParseState.SUB_REMAINER, ParseState.SUB_RULESET_NAME}:
elif state in {ParseState.SUB_REMAINDER, ParseState.SUB_RULESET_NAME}:
if is_sub_optional:
state = ParseState.SUB_OPTIONAL_AFTER
else:
Expand All @@ -196,7 +196,7 @@ def parse(value_str: str, text: str, radix: int = 10) -> "Optional[RbnfRule]":
raise ValueError(f"Got {c} in {state}")
elif c == "%":
# =%rule_name= replacement
if state in {ParseState.SUB_QUOTIENT, ParseState.SUB_REMAINER}:
if state in {ParseState.SUB_QUOTIENT, ParseState.SUB_REMAINDER}:
assert isinstance(part, SubRulePart)
state = ParseState.SUB_RULESET_NAME
part.ruleset_name = ""
Expand Down Expand Up @@ -493,14 +493,22 @@ def iter_format_number(
yield part.text
elif isinstance(part, SubRulePart):
if (part.type == SubType.QUOTIENT) and (q > 0):
if (q == 0) and (part.ruleset_name is None):
# Rulesets can use quotients of zero
continue

if part.text_before:
yield part.text_before
yield from self.iter_format_number(
q, ruleset_name=part.ruleset_name or ruleset_name
)
if part.text_after:
yield part.text_after
elif (part.type == SubType.REMAINER) and (r > 0):
elif part.type == SubType.REMAINDER:
if (r == 0) and (part.ruleset_name is None):
# Rulesets can use remainders of zero
continue

if part.text_before:
yield part.text_before
yield from self.iter_format_number(
Expand Down

0 comments on commit 9b64edc

Please sign in to comment.