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
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}