Skip to content

feat(parser): anthem subject qualifiers "with a mana ability" / "with no abilities"#5452

Merged
matthewevans merged 4 commits into
phase-rs:mainfrom
nickmopen:feat/anthem-ability-subject-qualifier
Jul 9, 2026
Merged

feat(parser): anthem subject qualifiers "with a mana ability" / "with no abilities"#5452
matthewevans merged 4 commits into
phase-rs:mainfrom
nickmopen:feat/anthem-ability-subject-qualifier

Conversation

@nickmopen

Copy link
Copy Markdown
Contributor

Problem

An anthem subject phrase carrying a "with a mana ability" or "with no abilities" object qualifier did not parse. No subject-filter arm recognized the qualifier, so the whole static line fell through to Effect::Unimplemented { name: "static_structure", .. } and produced no continuous static.

Affected real cards:

  • Raggadragga, GoregutterEach creature you control with a mana ability gets +2/+2.
  • Muraganda PetroglyphsCreatures with no abilities get +2/+2.
  • Ruxa, Patient ProfessorCreatures you control with no abilities get +1/+1.

Fix

Strip the trailing qualifier in parse_continuous_subject_filter, parse the base subject recursively, and attach the matching FilterProp. Both properties are already fully evaluated at runtime by game::filter (HasManaAbility via the authoritative mana-ability classifier; HasNoAbilities via object_has_no_abilities) — so this is a grammar-only seam that reuses existing modeling.

Placing it on the shared subject-filter parser covers every subject shape at once — singular (Each creature you control …), global (Creatures …), controller-scoped plural (Creatures you control …), and subtype (Elf creatures you control …). The qualifier must sit at the very end of the subject phrase (after empty) so a mid-phrase with … clause is not misclaimed.

Tests

Three new oracle_tests.rs tests (Raggadragga / Ruxa / Muraganda) assert each line produces a continuous static — no static_structure Unimplemented — whose affected filter carries the expected FilterProp.

Regression: parser::oracle module 7604 passed, 0 failed. cargo fmt, clippy (-D warnings), and the parser-combinator / engine-authorities gates are clean. The fix lands entirely in oracle_static/shared.rs.

… no abilities"

An anthem subject phrase carrying a "with a mana ability" or "with no
abilities" object qualifier failed to parse: the qualifier was not
recognized by any subject-filter arm, so the whole static line fell
through to Effect::Unimplemented { name: "static_structure", .. } and no
continuous static was produced.

Strip the trailing qualifier in parse_continuous_subject_filter, parse
the base subject recursively, and attach the matching FilterProp. Both
properties are already fully evaluated at runtime by game::filter
(HasManaAbility via the authoritative mana-ability classifier,
HasNoAbilities via object_has_no_abilities), so this is a grammar-only
seam that reuses existing modeling. Placing it on the shared subject
filter covers every subject shape at once:

- Raggadragga, Goregutter  "Each creature you control with a mana ability gets +2/+2."
- Muraganda Petroglyphs     "Creatures with no abilities get +2/+2."
- Ruxa, Patient Professor    "Creatures you control with no abilities get +1/+1."

The qualifier must sit at the very end of the subject phrase so a
mid-phrase "with ..." clause is not misclaimed.
@nickmopen nickmopen requested a review from matthewevans as a code owner July 9, 2026 18:26

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds support for parsing trailing subject qualifiers "with a mana ability" and "with no abilities" in continuous subject filters, mapping them to runtime-evaluated filter properties. It also introduces corresponding test cases. Feedback is provided regarding a potential UTF-8 slicing hazard where slicing tp.original using the byte length of the lowercased prefix base_lower can cause panics or character corruption if case conversion alters the byte length of any characters.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread crates/engine/src/parser/oracle_static/shared.rs Outdated
@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown

Parse changes introduced by this PR · 1 card(s), 2 signature(s) (baseline: main 58fa4c710cfa)

1 card(s) · static/Continuous · added: Continuous (affects=with a mana ability you control creature, mods=power +2, toughness +2)

Examples: Raggadragga, Goreguts Boss

1 card(s) · ability/static_structure · removed: static_structure

Examples: Raggadragga, Goreguts Boss

@matthewevans matthewevans self-assigned this Jul 9, 2026

@matthewevans matthewevans left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved after maintainer fixups. Evidence: current head 9478a74 is CI green; parse-diff refreshed against main 58fa4c7 and shows only Raggadragga gaining the intended continuous static and losing static_structure; Gemini's lower/original slicing concern was resolved by switching the qualifier parser to nom suffix parsing plus lower_subslice_to_original.

@matthewevans matthewevans added the enhancement New feature or request label Jul 9, 2026
@matthewevans matthewevans added this pull request to the merge queue Jul 9, 2026
@matthewevans matthewevans removed their assignment Jul 9, 2026
Merged via the queue into phase-rs:main with commit d61c941 Jul 9, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants