Skip to main content

parse

Function parse 

Source
pub fn parse(input: &str) -> Result<Generator, &str>
Expand description

parse builds a generator from the given input string. If any of the string can be parsed a generator is returned. If no generator can be built then an error is returned with the input string.

  • Examples
use rand::prelude::*;
let mut rng = rand::rng();
let g = dice_nom::parse("2d4! + 2d6! < 3d8!");
assert!(g.is_ok());
if let Ok(g) = g {
    let results = g.generate(&mut rng);
    assert!(!results.rhs.is_none());
}

let g = dice_nom::parse("attack badger");
assert!(!g.is_ok());
assert_eq!(g, Err("attack badger"));
Examples found in repository?
examples/basic_usage.rs (line 35)
8fn main() {
9    let mut rng = rand::rng();
10
11    println!("=== Basic Dice Rolling ===");
12
13    // Simple dice rolls using the roller function
14    let simple_d6 = roller(1, 6, None);
15    let result = simple_d6.generate(&mut rng);
16    println!("1d6: {}", result);
17
18    let multiple_dice = roller(3, 6, None);
19    let result = multiple_dice.generate(&mut rng);
20    println!("3d6: {}", result);
21
22    println!("\n=== Parsing Complex Expressions ===");
23
24    // Parse and roll various dice expressions
25    let expressions = vec![
26        "3d6+4",   // Basic arithmetic
27        "2d8-1",   // Subtraction
28        "1d20+5",  // Common D&D roll
29        "4d6^3",   // Keep highest 3 of 4 dice
30        "2d20ADV", // Advantage (roll twice, keep higher)
31        "2d20DIS", // Disadvantage (roll twice, keep lower)
32    ];
33
34    for expr in expressions {
35        match parse(expr) {
36            Ok(generator) => {
37                let result = generator.generate(&mut rng);
38                println!("{}: {}", expr, result);
39            }
40            Err(_) => println!("Failed to parse: {}", expr),
41        }
42    }
43
44    println!("\n=== Exploding Dice ===");
45
46    // Exploding dice examples
47    let exploding_expressions = vec![
48        "3d6!",   // Explode on max (reroll once if all dice are 6)
49        "2d8!!",  // Explode until (keep rerolling while all dice are max)
50        "4d6*",   // Explode each (reroll each die that's max)
51        "3d10**", // Explode each until (keep rerolling each max die)
52    ];
53
54    for expr in exploding_expressions {
55        if let Ok(generator) = parse(expr) {
56            let result = generator.generate(&mut rng);
57            println!("{}: {}", expr, result);
58        }
59    }
60
61    println!("\n=== Target Numbers and Success Counting ===");
62
63    // Target-based rolling
64    let target_expressions = vec![
65        "6d6[4]",     // Count dice >= 4 as successes
66        "4d10(3)",    // Count dice <= 3 as successes
67        "3d6{12}",    // Success if total >= 12
68        "2d10{15,5}", // 1 success at 15, +1 for every 5 above
69    ];
70
71    for expr in target_expressions {
72        if let Ok(generator) = parse(expr) {
73            let result = generator.generate(&mut rng);
74            println!("{}: {}", expr, result);
75        }
76    }
77
78    println!("\n=== Pool Manipulation ===");
79
80    // Pool operations
81    let pool_expressions = vec![
82        "5d6^3", // Keep highest 3
83        "5d6`2", // Keep lowest 2
84        "6d6~4", // Keep middle 4
85        "5d6Y",  // Keep largest group of matching dice
86    ];
87
88    for expr in pool_expressions {
89        if let Ok(generator) = parse(expr) {
90            let result = generator.generate(&mut rng);
91            println!("{}: {}", expr, result);
92        }
93    }
94
95    println!("\n=== Comparisons ===");
96
97    // Comparison operations
98    let comparison_expressions = vec![
99        "3d6 > 2d8",    // Left vs right comparison
100        "1d20+5 >= 15", // Skill check vs DC
101        "2d6 = 7",      // Exact match
102        "3d6 <=> 3d6",  // Three-way comparison (-1, 0, or 1)
103    ];
104
105    for expr in comparison_expressions {
106        if let Ok(generator) = parse(expr) {
107            let result = generator.generate(&mut rng);
108            println!(
109                "{}: {} ({})",
110                expr,
111                result,
112                if result.sum() == 1 {
113                    "Success"
114                } else if result.sum() == -1 {
115                    "Failure"
116                } else if result.sum() == 0 {
117                    "Tie/False"
118                } else {
119                    "Unknown"
120                }
121            );
122        }
123    }
124
125    println!("\n=== Multiple Rolls ===");
126
127    // Demonstrate multiple rolls of the same expression
128    if let Ok(generator) = parse("3d6") {
129        println!("Rolling 3d6 five times:");
130        for i in 1..=5 {
131            let result = generator.generate(&mut rng);
132            println!("Roll {}: {}", i, result);
133        }
134    }
135
136    println!("\n=== Error Handling ===");
137
138    // Show error handling for invalid expressions
139    let invalid_expressions = vec!["attack the goblin", "3d6 + invalid", "d", ""];
140
141    for expr in invalid_expressions {
142        match parse(expr) {
143            Ok(_) => println!("{}: Parsed successfully (unexpected!)", expr),
144            Err(remaining) => println!("{}: Failed to parse, remaining: '{}'", expr, remaining),
145        }
146    }
147}
More examples
Hide additional examples
examples/gaming_systems.rs (line 16)
8fn main() {
9    let mut rng = rand::rng();
10
11    println!("=== D&D 5th Edition Examples ===");
12
13    // Character creation - roll stats
14    println!("Rolling ability scores (4d6, drop lowest):");
15    for ability in ["STR", "DEX", "CON", "INT", "WIS", "CHA"] {
16        if let Ok(generator) = parse("4d6^3") {
17            let result = generator.generate(&mut rng);
18            println!("{}: {}", ability, result);
19        }
20    }
21
22    // Combat rolls
23    println!("\nCombat examples:");
24    let combat_rolls = vec![
25        ("Attack roll (d20+5)", "1d20+5"),
26        ("Damage (longsword)", "1d8+3"),
27        ("Sneak attack", "1d8+3+3d6"),
28        ("Fireball damage", "8d6"),
29        ("Healing potion", "2d4+2"),
30    ];
31
32    for (description, expr) in combat_rolls {
33        if let Ok(generator) = parse(expr) {
34            let result = generator.generate(&mut rng);
35            println!("{}: {}", description, result);
36        }
37    }
38
39    // Advantage/Disadvantage
40    println!("\nAdvantage and Disadvantage:");
41    let adv_dis_rolls = vec![
42        ("Attack with Advantage", "1d20ADV+5"),
43        ("Stealth with Disadvantage", "1d20DIS+2"),
44    ];
45
46    for (description, expr) in adv_dis_rolls {
47        if let Ok(generator) = parse(expr) {
48            let result = generator.generate(&mut rng);
49            println!("{}: {}", description, result);
50        }
51    }
52
53    println!("\n=== Call of Cthulhu  ===");
54
55    // Character creation - roll stats
56    println!("Generate statistics:");
57    let character_stats = vec![
58        ("STR (Strength)", "3d6x5"),
59        ("CON (Constitution)", "3d6x5"),
60        ("SIZ (Size)", "2d6+6x5"),
61        ("DEX (Dexterity)", "3d6x5"),
62        ("APP (Appearance)", "3d6x5"),
63        ("INT (Intelligence)", "2d6+6x5"),
64        ("POW (Power)", "3d6x5"),
65        ("EDU (Education)", "2d6+6x5"),
66        ("Luck", "3d6x5"),
67    ];
68
69    for (description, expr) in character_stats {
70        if let Ok(generator) = parse(expr) {
71            let result = generator.generate(&mut rng);
72            println!("{}: {}", description, result);
73        }
74    }
75
76    println!("\n=== World of Darkness Examples ===");
77
78    // Success counting system
79    let wod_rolls = vec![
80        ("Dexterity + Athletics (6 dice)", "6d10[6]"),
81        ("Manipulation + Subterfuge (4 dice)", "4d10[6]"),
82        ("Intelligence + Academics (7 dice)", "7d10[6]"),
83    ];
84
85    for (description, expr) in wod_rolls {
86        if let Ok(generator) = parse(expr) {
87            let result = generator.generate(&mut rng);
88            println!("{}: {} successes", description, result.lhs.hits());
89        }
90    }
91
92    println!("\n=== Shadowrun Examples ===");
93
94    // Edge cases and exploding dice
95    let shadowrun_rolls = vec![
96        ("Firearms skill test", "8d6[5]"),
97        ("Edge-enhanced roll", "8d6**[5]"),
98        ("Damage resistance", "6d6[5]"),
99    ];
100
101    for (description, expr) in shadowrun_rolls {
102        if let Ok(generator) = parse(expr) {
103            let result = generator.generate(&mut rng);
104            println!("{}: {} hits", description, result.lhs.hits());
105        }
106    }
107
108    println!("\n=== GURPS Examples ===");
109
110    // 3d6 roll-under system
111    let gurps_rolls = vec![
112        ("Skill check vs 12", "3d6 <= 12"),
113        ("Attribute check vs 14", "3d6 <= 14"),
114        ("Hard skill check vs 10", "3d6 <= 10"),
115    ];
116
117    for (description, expr) in gurps_rolls {
118        if let Ok(generator) = parse(expr) {
119            let result = generator.generate(&mut rng);
120            let success = result.sum() == 1;
121            println!(
122                "{}: {} ({})",
123                description,
124                result.lhs.sum(),
125                if success { "Success" } else { "Failure" }
126            );
127        }
128    }
129
130    println!("\n=== Fate/Fudge Examples ===");
131
132    // Fudge dice simulation using d3 (1=-, 2=blank, 3=+)
133    println!("Fate dice (simulated with d3s where 1=-, 2=0, 3=+):");
134    for i in 1..=3 {
135        if let Ok(generator) = parse("4d3--2") {
136            let result = generator.generate(&mut rng);
137            let fate_result = result.sum();
138            println!(
139                "Roll {}: {} ({})",
140                i,
141                result,
142                match fate_result {
143                    -4..=-3 => "Terrible",
144                    -2..=-1 => "Poor",
145                    0 => "Mediocre",
146                    1..=2 => "Good",
147                    3..=4 => "Great",
148                    _ => "Exceptional",
149                }
150            );
151        }
152    }
153
154    println!("\n=== Savage Worlds Examples ===");
155
156    // Exploding dice and Aces
157    let savage_worlds_rolls = vec![
158        ("Fighting with d8", "1d8!"),
159        ("Shooting with d10", "1d10!"),
160        ("Wild die + trait", "1d6! + 1d8!"),
161        ("Damage with d6+2", "1d6!+2"),
162    ];
163
164    for (description, expr) in savage_worlds_rolls {
165        if let Ok(generator) = parse(expr) {
166            let result = generator.generate(&mut rng);
167            let total = result.sum();
168            println!(
169                "{}: {} ({})",
170                description,
171                result,
172                if total >= 4 { "Success" } else { "Failure" }
173            );
174        }
175    }
176}