manabrew_engine/parsing/
amount.rs1#[derive(Debug, Clone, PartialEq, Eq)]
2pub enum AmountExpr {
3 Literal(i32),
4 X,
5 SVar(String),
6 Raw(String),
7}
8
9impl AmountExpr {
10 pub fn from_semantic(amount: &crate::parsing::SemanticAmount<'_>) -> Self {
11 match amount {
12 crate::parsing::SemanticAmount::Literal(value) => Self::Literal(*value),
13 crate::parsing::SemanticAmount::X => Self::X,
14 crate::parsing::SemanticAmount::SVar(name) => Self::SVar((*name).to_string()),
15 crate::parsing::SemanticAmount::Any
16 | crate::parsing::SemanticAmount::All
17 | crate::parsing::SemanticAmount::Expression(_) => Self::Raw(amount_to_raw(amount)),
18 }
19 }
20
21 pub fn parse(raw: &str) -> Self {
22 let trimmed = raw.trim();
23 if let Ok(value) = trimmed.parse::<i32>() {
24 Self::Literal(value)
25 } else if trimmed == "X" {
26 Self::X
27 } else if trimmed.is_empty() {
28 Self::Raw(String::new())
29 } else if is_svar_name(trimmed) {
30 Self::SVar(trimmed.to_string())
31 } else {
32 Self::Raw(trimmed.to_string())
33 }
34 }
35
36 pub fn resolve_for_spell_ability(
37 &self,
38 game: &crate::game::GameState,
39 sa: &crate::spellability::SpellAbility,
40 default: i32,
41 ) -> i32 {
42 match self {
43 Self::Literal(value) => *value,
44 Self::X => crate::svar::resolve_numeric_value(game, sa, "X", default),
45 Self::SVar(name) | Self::Raw(name) => {
46 crate::svar::resolve_numeric_value(game, sa, name, default)
47 }
48 }
49 }
50}
51
52fn amount_to_raw(amount: &crate::parsing::SemanticAmount<'_>) -> String {
53 match amount {
54 crate::parsing::SemanticAmount::Literal(value) => value.to_string(),
55 crate::parsing::SemanticAmount::X => "X".to_string(),
56 crate::parsing::SemanticAmount::Any => "Any".to_string(),
57 crate::parsing::SemanticAmount::All => "All".to_string(),
58 crate::parsing::SemanticAmount::SVar(name)
59 | crate::parsing::SemanticAmount::Expression(name) => (*name).to_string(),
60 }
61}
62
63fn is_svar_name(raw: &str) -> bool {
64 let mut chars = raw.chars();
65 let Some(first) = chars.next() else {
66 return false;
67 };
68 (first == '_' || first.is_ascii_alphabetic())
69 && chars.all(|c| c == '_' || c.is_ascii_alphanumeric())
70}