Skip to main content

parse

Function parse 

Source
pub fn parse(source: &str) -> Result<Model>
Expand description

Parse a MiniZinc model from source text into an AST

§Arguments

  • source - MiniZinc source code as a string

§Returns

An AST (Abstract Syntax Tree) representing the model, or a parsing error

§Example

let ast = zelen::parse("var 1..10: x; solve satisfy;");
assert!(ast.is_ok());
Examples found in repository?
examples/simple_constraints.rs (line 17)
5fn main() -> Result<(), Box<dyn std::error::Error>> {
6    let source = r#"
7        var 1..10: x;
8        var 1..10: y;
9        
10        constraint x < y;
11        constraint x + y < 15;
12        
13        solve satisfy;
14    "#;
15
16    println!("Parsing model with constraints...");
17    let ast = zelen::parse(source)?;
18    
19    println!("Translating to Selen Model...");
20    let model = zelen::translate(&ast)?;
21    
22    println!("Solving...");
23    match model.solve() {
24        Ok(solution) => {
25            println!("\n✓ Solution found!");
26            println!("{:?}", solution);
27        }
28        Err(e) => {
29            println!("No solution found: {:?}", e);
30        }
31    }
32
33    Ok(())
34}
More examples
Hide additional examples
examples/sudoku.rs (line 9)
3fn main() {
4    let mzn_code = fs::read_to_string("examples/models/sudoku.mzn")
5        .expect("Failed to read sudoku.mzn");
6    
7    println!("=== Parsing Sudoku Example ===\n");
8    
9    let ast = match zelen::parse(&mzn_code) {
10        Ok(ast) => {
11            println!("✓ Parsing successful!");
12            println!("AST contains {} items", ast.items.len());
13            ast
14        }
15        Err(e) => {
16            println!("✗ Parsing failed: {}", e);
17            std::process::exit(1);
18        }
19    };
20    
21    println!("\n=== Translating Sudoku Example ===\n");
22    
23    match zelen::translate(&ast) {
24        Ok(_model) => {
25            println!("✓ Translation successful!");
26            println!("Model created successfully with 2D array constraints");
27        }
28        Err(e) => {
29            println!("✗ Translation failed: {}", e);
30            std::process::exit(1);
31        }
32    };
33}
examples/boolean_logic_demo.rs (line 48)
29fn example_boolean_and_or() {
30    println!("Example 1: Boolean AND and OR");
31    
32    let source = r#"
33        var bool: lights_on;
34        var bool: door_open;
35        var bool: alarm_active;
36        
37        % Alarm is active if lights are on AND door is open
38        constraint alarm_active <-> (lights_on /\ door_open);
39        
40        % At least one safety feature must be active
41        constraint lights_on \/ alarm_active;
42        
43        solve satisfy;
44    "#;
45    
46    println!("MiniZinc Source:\n{}", source);
47    
48    match parse(source) {
49        Ok(ast) => {
50            match Translator::translate_with_vars(&ast) {
51                Ok(model_data) => {
52                    println!("✓ Translated to Selen Model");
53                    
54                    match model_data.model.solve() {
55                        Ok(solution) => {
56                            println!("✓ Solution found!");
57                            
58                            for (name, &var_id) in &model_data.bool_vars {
59                                if let selen::variables::Val::ValI(val) = solution[var_id] {
60                                    println!("  {} = {}", name, val != 0);
61                                }
62                            }
63                        }
64                        Err(e) => println!("✗ No solution: {:?}", e),
65                    }
66                }
67                Err(e) => println!("✗ Translation error: {:?}", e),
68            }
69        }
70        Err(e) => println!("✗ Parse error: {:?}", e),
71    }
72}
73
74fn example_boolean_not() {
75    println!("Example 2: Boolean NOT");
76    
77    let source = r#"
78        var bool: system_enabled;
79        var bool: maintenance_mode;
80        
81        % System is enabled only when NOT in maintenance mode
82        constraint system_enabled <-> not maintenance_mode;
83        
84        % Must be in one of the two states
85        constraint system_enabled \/ maintenance_mode;
86        
87        solve satisfy;
88    "#;
89    
90    println!("MiniZinc Source:\n{}", source);
91    
92    match parse(source) {
93        Ok(ast) => {
94            match Translator::translate_with_vars(&ast) {
95                Ok(model_data) => {
96                    println!("✓ Translated to Selen Model");
97                    
98                    match model_data.model.solve() {
99                        Ok(solution) => {
100                            println!("✓ Solution found!");
101                            
102                            for (name, &var_id) in &model_data.bool_vars {
103                                if let selen::variables::Val::ValI(val) = solution[var_id] {
104                                    println!("  {} = {}", name, val != 0);
105                                }
106                            }
107                        }
108                        Err(e) => println!("✗ No solution: {:?}", e),
109                    }
110                }
111                Err(e) => println!("✗ Translation error: {:?}", e),
112            }
113        }
114        Err(e) => println!("✗ Parse error: {:?}", e),
115    }
116}
117
118fn example_boolean_implication() {
119    println!("Example 3: Boolean Implication");
120    
121    let source = r#"
122        var bool: raining;
123        var bool: umbrella;
124        var bool: wet;
125        
126        % If it's raining and no umbrella, then you get wet
127        constraint (raining /\ not umbrella) -> wet;
128        
129        % If you have umbrella, you don't get wet
130        constraint umbrella -> not wet;
131        
132        % It is raining
133        constraint raining;
134        
135        solve satisfy;
136    "#;
137    
138    println!("MiniZinc Source:\n{}", source);
139    
140    match parse(source) {
141        Ok(ast) => {
142            match Translator::translate_with_vars(&ast) {
143                Ok(model_data) => {
144                    println!("✓ Translated to Selen Model");
145                    
146                    match model_data.model.solve() {
147                        Ok(solution) => {
148                            println!("✓ Solution found!");
149                            
150                            for (name, &var_id) in &model_data.bool_vars {
151                                if let selen::variables::Val::ValI(val) = solution[var_id] {
152                                    println!("  {} = {}", name, val != 0);
153                                }
154                            }
155                        }
156                        Err(e) => println!("✗ No solution: {:?}", e),
157                    }
158                }
159                Err(e) => println!("✗ Translation error: {:?}", e),
160            }
161        }
162        Err(e) => println!("✗ Parse error: {:?}", e),
163    }
164}
165
166fn example_float_arithmetic() {
167    println!("Example 4: Float Arithmetic in Constraints");
168    
169    let source = r#"
170        var 0.0..100.0: price;
171        var 0.0..1.0: tax_rate;
172        var 0.0..150.0: total;
173        
174        % Total is price plus tax
175        constraint total = price + (price * tax_rate);
176        
177        % Total must be under budget
178        constraint total <= 100.0;
179        
180        % Reasonable tax rate
181        constraint tax_rate >= 0.05;
182        constraint tax_rate <= 0.20;
183        
184        solve satisfy;
185    "#;
186    
187    println!("MiniZinc Source:\n{}", source);
188    
189    match parse(source) {
190        Ok(ast) => {
191            match Translator::translate_with_vars(&ast) {
192                Ok(model_data) => {
193                    println!("✓ Translated to Selen Model");
194                    
195                    match model_data.model.solve() {
196                        Ok(solution) => {
197                            println!("✓ Solution found!");
198                            
199                            for (name, &var_id) in &model_data.float_vars {
200                                if let selen::variables::Val::ValF(val) = solution[var_id] {
201                                    println!("  {} = {:.2}", name, val);
202                                }
203                            }
204                        }
205                        Err(e) => println!("✗ No solution: {:?}", e),
206                    }
207                }
208                Err(e) => println!("✗ Translation error: {:?}", e),
209            }
210        }
211        Err(e) => println!("✗ Parse error: {:?}", e),
212    }
213}
214
215fn example_array_indexing() {
216    println!("Example 5: Array Indexing in Constraints");
217    
218    let source = r#"
219        array[1..5] of var 1..10: values;
220        
221        % First element must be less than 5
222        constraint values[1] < 5;
223        
224        % Third element must be greater than 5
225        constraint values[3] > 5;
226        
227        % Fifth element must equal first element plus second
228        constraint values[5] = values[1] + values[2];
229        
230        solve satisfy;
231    "#;
232    
233    println!("MiniZinc Source:\n{}", source);
234    
235    match parse(source) {
236        Ok(ast) => {
237            match Translator::translate_with_vars(&ast) {
238                Ok(model_data) => {
239                    println!("✓ Translated to Selen Model");
240                    
241                    let model = model_data.model;
242                    match model.solve() {
243                        Ok(solution) => {
244                            println!("✓ Solution found!");
245                            
246                            // Get the array variable IDs
247                            if let Some(values_arr) = model_data.int_var_arrays.get("values") {
248                                print!("  values = [");
249                                for (i, var_id) in values_arr.iter().enumerate() {
250                                    if i > 0 {
251                                        print!(", ");
252                                    }
253                                    print!("{}", solution.get_int(*var_id));
254                                }
255                                println!("]");
256                            }
257                        }
258                        Err(e) => println!("✗ No solution: {:?}", e),
259                    }
260                }
261                Err(e) => println!("✗ Translation error: {:?}", e),
262            }
263        }
264        Err(e) => println!("✗ Parse error: {:?}", e),
265    }
266}
examples/solve_nqueens.rs (line 15)
5fn main() -> Result<(), Box<dyn std::error::Error>> {
6    // Simple N-Queens model
7    let source = r#"
8        int: n = 4;
9        array[1..n] of var 1..n: queens;
10        constraint alldifferent(queens);
11        solve satisfy;
12    "#;
13
14    println!("Parsing MiniZinc model...");
15    let ast = zelen::parse(source)?;
16    println!("Parsed {} items", ast.items.len());
17
18    println!("\nTranslating to Selen Model...");
19    let translated = zelen::Translator::translate_with_vars(&ast)?;
20    println!("Translation successful!");
21
22    println!("\nSolving...");
23    match translated.model.solve() {
24        Ok(solution) => {
25            println!("✓ Solution found!");
26            
27            // Extract and display the queens array values
28            if let Some(queens) = translated.int_var_arrays.get("queens") {
29                print!("\nQueens array: [");
30                for (i, var_id) in queens.iter().enumerate() {
31                    if i > 0 { print!(", "); }
32                    match solution[*var_id] {
33                        selen::variables::Val::ValI(val) => print!("{}", val),
34                        _ => print!("?"),
35                    }
36                }
37                println!("]");
38                
39                println!("\nInterpretation: Queen in row i is placed in column queens[i]");
40            }
41            
42            println!("\nSolve stats: {} propagations, {} nodes, {:?}",
43                solution.stats.propagation_count,
44                solution.stats.node_count,
45                solution.stats.solve_time
46            );
47        }
48        Err(e) => {
49            println!("No solution found: {:?}", e);
50        }
51    }
52
53    Ok(())
54}
examples/queens4.rs (line 30)
5fn main() -> Result<(), Box<dyn std::error::Error>> {
6    // N-Queens with all constraints
7    // Note: This example currently only has column constraints (alldifferent)
8    // Full N-Queens needs diagonal constraints too:
9    //   - queens[i] + i != queens[j] + j  (ascending diagonal)
10    //   - queens[i] - i != queens[j] - j  (descending diagonal)
11    // These will be added when we implement more constraint types
12    let source = r#"
13        int: n = 4;
14        array[1..n] of var 1..n: queens;
15        
16        % All queens must be in different rows (implicit from domain)
17        % All queens must be in different columns
18        constraint alldifferent(queens);
19        
20        % TODO: Add diagonal constraints when supported:
21        % constraint forall(i,j in 1..n where i < j)(
22        %     queens[i] + i != queens[j] + j /\
23        %     queens[i] - i != queens[j] - j
24        % );
25        
26        solve satisfy;
27    "#;
28
29    println!("Parsing 4-Queens problem...");
30    let ast = zelen::parse(source)?;
31    
32    println!("Translating to Selen Model...");
33    let translated = zelen::Translator::translate_with_vars(&ast)?;
34    
35    println!("Solving...");
36    match translated.model.solve() {
37        Ok(solution) => {
38            println!("\n✓ Solution found!");
39            
40            // Extract the queens array
41            if let Some(queens) = translated.int_var_arrays.get("queens") {
42                println!("\nQueens positions:");
43                for (i, var_id) in queens.iter().enumerate() {
44                    if let selen::variables::Val::ValI(col) = solution[*var_id] {
45                        println!("  Queen {} (row {}) is in column {}", i + 1, i + 1, col);
46                    }
47                }
48                
49                println!("\n⚠️  Note: This solution satisfies 'alldifferent' (different columns)");
50                println!("   but diagonal constraints are not yet implemented.");
51                println!("   All queens on the main diagonal is a valid solution for column-only constraints!");
52                
53                // Print the board
54                println!("\nChessboard (. = empty, Q = queen):");
55                for row in 0..4 {
56                    print!("  ");
57                    for col in 0..4 {
58                        let queen_var = queens[row];
59                        if let selen::variables::Val::ValI(queen_col) = solution[queen_var] {
60                            if queen_col == (col + 1) as i32 {
61                                print!("Q ");
62                            } else {
63                                print!(". ");
64                            }
65                        }
66                    }
67                    println!();
68                }
69            }
70        }
71        Err(e) => {
72            println!("No solution found: {:?}", e);
73        }
74    }
75
76    Ok(())
77}
examples/parser_demo.rs (line 29)
3fn main() {
4    println!("=== MiniZinc Parser Examples ===\n");
5    
6    // Example 1: N-Queens problem
7    println!("Example 1: N-Queens Problem");
8    let nqueens = r#"
9% N-Queens Problem
10int: n = 8;
11
12% Decision variables: queen position in each row
13array[1..n] of var 1..n: queens;
14
15% All queens in different columns
16constraint alldifferent(queens);
17
18% No two queens on same diagonal
19constraint forall(i in 1..n, j in i+1..n) (
20    queens[i] != queens[j] + (j - i) /\
21    queens[i] != queens[j] - (j - i)
22);
23
24solve satisfy;
25
26output ["queens = ", show(queens), "\n"];
27    "#;
28    
29    match parse(nqueens) {
30        Ok(model) => println!("✓ Successfully parsed {} items\n", model.items.len()),
31        Err(e) => println!("✗ Parse error:\n{}\n", e),
32    }
33    
34    // Example 2: Simple optimization
35    println!("Example 2: Simple Optimization");
36    let optimization = r#"
37int: budget = 100;
38array[1..5] of int: costs = [10, 20, 15, 30, 25];
39array[1..5] of int: values = [50, 100, 75, 150, 125];
40array[1..5] of var 0..1: x;
41
42constraint sum(i in 1..5)(costs[i] * x[i]) <= budget;
43
44solve maximize sum(i in 1..5)(values[i] * x[i]);
45    "#;
46    
47    match parse(optimization) {
48        Ok(model) => println!("✓ Successfully parsed {} items\n", model.items.len()),
49        Err(e) => println!("✗ Parse error:\n{}\n", e),
50    }
51    
52    // Example 3: Syntax error - missing colon
53    println!("Example 3: Syntax Error (missing colon)");
54    let error1 = r#"
55int n = 5;
56var 1..n: x;
57    "#;
58    
59    match parse(error1) {
60        Ok(_) => println!("✗ Should have failed!\n"),
61        Err(e) => println!("✓ Caught error:\n{}\n", e),
62    }
63    
64    // Example 4: Syntax error - missing semicolon
65    println!("Example 4: Syntax Error (missing semicolon)");
66    let error2 = r#"
67int: n = 5
68var 1..n: x;
69    "#;
70    
71    match parse(error2) {
72        Ok(_) => println!("✗ Should have failed!\n"),
73        Err(e) => println!("✓ Caught error:\n{}\n", e),
74    }
75    
76    // Example 5: Complex expressions
77    println!("Example 5: Complex Expressions");
78    let complex = r#"
79int: n = 10;
80array[1..n] of var 1..100: x;
81
82constraint sum(x) == 500;
83constraint forall(i in 1..n-1)(x[i] <= x[i+1]);
84constraint x[1] >= 10;
85constraint x[n] <= 90;
86
87solve minimize sum(i in 1..n)(x[i] * x[i]);
88    "#;
89    
90    match parse(complex) {
91        Ok(model) => println!("✓ Successfully parsed {} items\n", model.items.len()),
92        Err(e) => println!("✗ Parse error:\n{}\n", e),
93    }
94    
95    // Example 6: Array comprehension
96    println!("Example 6: Array Comprehension");
97    let array_comp = r#"
98int: n = 10;
99array[1..n] of int: squares = [i*i | i in 1..n];
100array[int] of int: evens = [i | i in 1..20 where i mod 2 == 0];
101    "#;
102    
103    match parse(array_comp) {
104        Ok(model) => println!("✓ Successfully parsed {} items\n", model.items.len()),
105        Err(e) => println!("✗ Parse error:\n{}\n", e),
106    }
107    
108    // Example 7: Set operations
109    println!("Example 7: Set Operations");
110    let sets = r#"
111set of int: S = {1, 3, 5, 7, 9};
112set of int: T = 1..10;
113var 1..10: x;
114
115constraint x in S;
116constraint x in T;
117    "#;
118    
119    match parse(sets) {
120        Ok(model) => println!("✓ Successfully parsed {} items\n", model.items.len()),
121        Err(e) => println!("✗ Parse error:\n{}\n", e),
122    }
123    
124    println!("=== All examples completed ===");
125}