Skip to content

parser: N-way Oxford-comma "you control" anthem subject drops middle list items (Death-Priest of Myrkul, Blex) #5751

Description

@minion1227

Summary

A continuous "get/have" static ability whose subject is a 3-or-more-item comma list ending in you control silently drops the middle list item(s). The subject filter comes out as an Or of only the first and last items; every item in between is lost, so the anthem buffs the wrong board.

This is the P/T-anthem sibling of the keyword-grant compound-subject path already fixed by #5383 (Shalai, Voice of Plenty). #5383 taught the keyword compound-subject splitter to handle N-item Oxford lists, but the controller-scoped continuous-subject filter (parse_shared_controller_compound_subject_filter) was left with a 2-item-only split, so P/T anthems with 3+ subtypes still regress.

Repro (verified Oracle text)

Card Oracle text (static line)
Death-Priest of Myrkul Skeletons, Vampires, and Zombies you control get +1/+1.
Blex, Vexing Pest Other Pests, Bats, Insects, Snakes, and Spiders you control get +1/+1.
Raphael, Fiendish Savior Other Demons, Devils, Imps, and Tieflings you control get +1/+1 and have lifelink.
Valley Questcaller Other Rabbits, Bats, Birds, and Mice you control get +1/+1.

Actual (Death-Priest of Myrkul)

The parsed affected filter drops Vampires:

Or [
  Typed { Creature, Subtype("Skeleton"), controller: You },
  Typed { Creature, Subtype("Zombie"),   controller: You },
]

Expected

Or [
  Typed { Creature, Subtype("Skeleton"), controller: You },
  Typed { Creature, Subtype("Vampire"),  controller: You },
  Typed { Creature, Subtype("Zombie"),   controller: You },
]

Blex/Raphael/Valley Questcaller lose 3 of their 4–5 listed subtypes the same way.

Root cause

parse_shared_controller_compound_subject_filter (crates/engine/src/parser/oracle_static/shared.rs) peels the shared you control / your opponents control suffix, then splits the remaining descriptor with a single scan_preceded(tag("and ")) — a 2-item left/right split. For a 3+ item Oxford list A, B, and C the only and sits at , and C, so it splits into:

  • left = A, B, — which re-parses to just A (the trailing , B, is discarded by the single-subtype type-phrase parse), and
  • right = C,

yielding Or[A, C] and silently dropping every middle item B.

Proposed fix

Generalize the existing 2-item seam to an N-way list split (parameterize, don't add a sibling handler):

  • Split the descriptor at every list connector (", ", ", and ", " and ", ", or ", ", and/or ", " and/or ") via a small composable nom combinator, instead of the single and -only split. Bare " or " is deliberately excluded (it would over-split an intra-subject qualifier such as with power 3 or greater); only the comma-anchored ", or " is a separator.
  • Strip the leading distribution word (Other, Each other, Each) once, and re-attach other to each item's subject so Other/Each other correctly distributes the source exclusion across the whole list (fixes Blex/Raphael/Valley Questcaller, where only the first item currently gets the exclusion).
  • Parse each item into its own controller-anchored filter and Or them. Keep the existing per-item filter_has_source_or_controller_anchor fail-safe so any mis-split bails to None (never emits a wrong Or).

Two-item compounds (Gisa "Skeletons and Zombies", "Artifacts and enchantments you control") are unchanged.

CR

CR 611.3a — a static ability's continuous effect applies at any moment to whatever its text indicates, so the affected-object filter must retain every listed subtype.

Notes

No existing open issue covers the P/T-anthem controller-scoped path; #5383 (closed) fixed only the keyword-grant compound-subject splitter, and #5740 (closed) fixed a different compound-subject axis (spell stack-scoping). This is a distinct, still-open gap.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions