fix(parser): guard bounded counter distribution choices - #5675
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces helper functions, constants, and unit tests to detect and parse bounded target cardinality phrases, specifically checking if a separator falls within such phrases. The code review feedback highlights two main issues: first, the use of static prefix lists and verbatim string matching for parsing Oracle phrases violates the style guide's requirement for modular, nom-based combinators; second, several newly added rules-touching parser functions lack the mandatory CR (Comprehensive Rules) annotations required by the style guide.
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.
| pub(super) const BOUNDED_TARGET_PREFIX_PHRASES: &[(&str, usize, usize)] = &[ | ||
| ("one or two target ", 1, 2), | ||
| ("one, two, or three target ", 1, 3), | ||
| ]; |
There was a problem hiding this comment.
Avoid verbatim string equality and static prefix lists (like BOUNDED_TARGET_PREFIX_PHRASES) for parsing Oracle phrases, as this bypasses the robust nom-based parser and creates fragile matches. Instead, decompose compound phrases into modular, reusable parsers for constituent parts (e.g., numbers, conjunctions, and 'target') and compose them using idiomatic combinator aggregates (like nested alt and tag sequences) to prevent combinatorial explosion and improve maintainability.
References
- Avoid verbatim string equality for parsing Oracle phrases as it bypasses the robust nom-based parser and creates fragile matches. Instead, decompose compound phrases into modular, reusable parsers for constituent parts and compose them using idiomatic combinator aggregates to prevent combinatorial explosion and improve maintainability.
| None | ||
| } | ||
|
|
||
| fn is_bounded_cardinality_boundary(c: char) -> bool { |
There was a problem hiding this comment.
[HIGH] Missing mandatory CR annotation for rules-touching parser function. Evidence: crates/engine/src/parser/oracle_effect/lower.rs:5039.
Why it matters: Every rules-touching line of engine code must carry a verified CR annotation to ensure strict fidelity to the Magic Comprehensive Rules.
Suggested fix: Add a CR 115.1d comment above the function definition.
| fn is_bounded_cardinality_boundary(c: char) -> bool { | |
| /// CR 115.1d: Check if a character is a boundary for bounded target cardinality. | |
| fn is_bounded_cardinality_boundary(c: char) -> bool { |
References
- Every rules-touching line of engine code must carry a comment of the form CR : . (link)
| fn parse_bounded_target_placeholder<'a>( | ||
| phrase: &'static str, | ||
| input: &'a str, | ||
| ) -> OracleResult<'a, &'a str> { |
There was a problem hiding this comment.
[HIGH] Missing mandatory CR annotation for rules-touching parser function. Evidence: crates/engine/src/parser/oracle_effect/lower.rs:5043.
Why it matters: Every rules-touching line of engine code must carry a verified CR annotation to ensure strict fidelity to the Magic Comprehensive Rules.
Suggested fix: Add a CR 115.1d comment above the function definition.
/// CR 115.1d: Parse a bounded target placeholder.
fn parse_bounded_target_placeholder<'a>(
phrase: &'static str,
input: &'a str,
) -> OracleResult<'a, &'a str> {References
- Every rules-touching line of engine code must carry a comment of the form CR : . (link)
| .parse(input) | ||
| } | ||
|
|
||
| fn parse_bounded_target_cardinality_phrase(input: &str) -> OracleResult<'_, ()> { |
There was a problem hiding this comment.
[HIGH] Missing mandatory CR annotation for rules-touching parser function. Evidence: crates/engine/src/parser/oracle_effect/lower.rs:5057.
Why it matters: Every rules-touching line of engine code must carry a verified CR annotation to ensure strict fidelity to the Magic Comprehensive Rules.
Suggested fix: Add a CR 115.1d comment above the function definition.
/// CR 115.1d: Parse a bounded target cardinality phrase.
fn parse_bounded_target_cardinality_phrase(input: &str) -> OracleResult<'_, ()> {References
- Every rules-touching line of engine code must carry a comment of the form CR : . (link)
| pub(super) fn selected_separator_inside_bounded_target_cardinality( | ||
| lower: &str, | ||
| separator: Range<usize>, | ||
| ) -> bool { |
There was a problem hiding this comment.
[HIGH] Missing mandatory CR annotation for rules-touching parser function. Evidence: crates/engine/src/parser/oracle_effect/lower.rs:5071.
Why it matters: Every rules-touching line of engine code must carry a verified CR annotation to ensure strict fidelity to the Magic Comprehensive Rules.
Suggested fix: Add a CR 115.1d comment above the function definition.
/// CR 115.1d: Check if a selected separator is inside a bounded target cardinality phrase.
pub(super) fn selected_separator_inside_bounded_target_cardinality(
lower: &str,
separator: Range<usize>,
) -> bool {References
- Every rules-touching line of engine code must carry a comment of the form CR : . (link)
|
Thanks for this, and welcome — the diagnosis here is correct, which is worth saying plainly before the outcome. Closing as already fixed. Issue #5613 was closed as completed by #5619 (merged Concretely,
One note for next time, because it would matter even on a rebased branch: this PR introduces Two things that would have caught this before you wrote the code, and are worth building into your habit here:
The reasoning was sound and the CR 601.2d insight was the right one. Please do pick up another issue — ideally one with no open PR linked against it, and I'd be glad to look at it. |
Summary
one, two, or three target ...cardinality text from being misclassified as an inlineChooseOneOfseparator.Card / Oracle
Selected card: Ajani, Mentor of Heroes
Scryfall Oracle verified:
Review Notes
Validation
C:\Program Files\Git\bin\bash.exe scripts/check-parser-combinators.shgit diff --checkNot Run
cargo fmt --all:cargois not available on PATH.