1
#![allow(clippy::legacy_numeric_constants)]
2
use conjure_core::ast::Declaration;
3
use conjure_core::error::Error;
4
use std::fs;
5
use std::rc::Rc;
6
use std::sync::{Arc, RwLock};
7
use tree_sitter::{Node, Parser, Tree};
8
use tree_sitter_essence::LANGUAGE;
9

            
10
use conjure_core::ast::{Atom, Domain, Expression, Literal, Name, Range, SymbolTable};
11

            
12
use crate::utils::conjure::EssenceParseError;
13
use conjure_core::context::Context;
14
use conjure_core::metadata::Metadata;
15
use conjure_core::Model;
16
use std::collections::{BTreeMap, BTreeSet};
17

            
18
623
pub fn parse_essence_file_native(
19
623
    path: &str,
20
623
    filename: &str,
21
623
    extension: &str,
22
623
    context: Arc<RwLock<Context<'static>>>,
23
623
) -> Result<Model, EssenceParseError> {
24
623
    let (tree, source_code) = get_tree(path, filename, extension);
25
623

            
26
623
    let mut model = Model::new(context);
27
623
    let root_node = tree.root_node();
28
2534
    for statement in named_children(&root_node) {
29
2534
        match statement.kind() {
30
2534
            "single_line_comment" => {}
31
2065
            "find_statement_list" => {
32
1008
                let var_hashmap = parse_find_statement(statement, &source_code);
33
2667
                for (name, decision_variable) in var_hashmap {
34
1659
                    model
35
1659
                        .as_submodel_mut()
36
1659
                        .symbols_mut()
37
1659
                        .insert(Rc::new(Declaration::new_var(name, decision_variable)));
38
1659
                }
39
            }
40
1057
            "constraint_list" => {
41
623
                let mut constraint_vec: Vec<Expression> = Vec::new();
42
1183
                for constraint in named_children(&statement) {
43
1183
                    if constraint.kind() != "single_line_comment" {
44
945
                        constraint_vec.push(parse_constraint(constraint, &source_code));
45
945
                    }
46
                }
47
623
                model.as_submodel_mut().add_constraints(constraint_vec);
48
            }
49
434
            "e_prime_label" => {}
50
42
            "letting_statement_list" => {
51
42
                let letting_vars = parse_letting_statement(statement, &source_code);
52
42
                model.as_submodel_mut().symbols_mut().extend(letting_vars);
53
42
            }
54
            _ => {
55
                let kind = statement.kind();
56
                return Err(EssenceParseError::ParseError(Error::Parse(
57
                    format!("Unrecognized top level statement kind: {kind}").to_owned(),
58
                )));
59
            }
60
        }
61
    }
62
623
    Ok(model)
63
623
}
64

            
65
623
fn get_tree(path: &str, filename: &str, extension: &str) -> (Tree, String) {
66
623
    let source_code = fs::read_to_string(format!("{path}/{filename}.{extension}"))
67
623
        .expect("Failed to read the source code file");
68
623
    let mut parser = Parser::new();
69
623
    parser.set_language(&LANGUAGE.into()).unwrap();
70
623
    (
71
623
        parser
72
623
            .parse(source_code.clone(), None)
73
623
            .expect("Failed to parse"),
74
623
        source_code,
75
623
    )
76
623
}
77

            
78
1008
fn parse_find_statement(find_statement_list: Node, source_code: &str) -> BTreeMap<Name, Domain> {
79
1008
    let mut vars = BTreeMap::new();
80

            
81
1029
    for find_statement in named_children(&find_statement_list) {
82
1029
        let mut temp_symbols = BTreeSet::new();
83
1029

            
84
1029
        let variable_list = find_statement
85
1029
            .named_child(0)
86
1029
            .expect("No variable list found");
87
1659
        for variable in named_children(&variable_list) {
88
1659
            let variable_name = &source_code[variable.start_byte()..variable.end_byte()];
89
1659
            temp_symbols.insert(variable_name);
90
1659
        }
91

            
92
1029
        let domain = find_statement.named_child(1).expect("No domain found");
93
1029
        let domain = parse_domain(domain, source_code);
94

            
95
2688
        for name in temp_symbols {
96
1659
            vars.insert(Name::UserName(String::from(name)), domain.clone());
97
1659
        }
98
    }
99
1008
    vars
100
1008
}
101

            
102
1043
fn parse_domain(domain: Node, source_code: &str) -> Domain {
103
1043
    let domain = domain.child(0).expect("No domain");
104
1043
    match domain.kind() {
105
1043
        "bool_domain" => Domain::BoolDomain,
106
959
        "int_domain" => parse_int_domain(domain, source_code),
107
14
        "variable" => {
108
14
            let variable_name = &source_code[domain.start_byte()..domain.end_byte()];
109
14
            Domain::DomainReference(Name::UserName(String::from(variable_name)))
110
        }
111
        _ => panic!("Not bool or int domain"),
112
    }
113
1043
}
114

            
115
945
fn parse_int_domain(int_domain: Node, source_code: &str) -> Domain {
116
945
    if int_domain.child_count() == 1 {
117
        Domain::IntDomain(vec![Range::Bounded(std::i32::MIN, std::i32::MAX)])
118
    } else {
119
945
        let mut ranges: Vec<Range<i32>> = Vec::new();
120
945
        let range_list = int_domain
121
945
            .named_child(0)
122
945
            .expect("No range list found (expression ranges not supported yet");
123
945
        for int_range in named_children(&range_list) {
124
945
            match int_range.kind() {
125
945
                "integer" => {
126
14
                    let integer_value = &source_code[int_range.start_byte()..int_range.end_byte()]
127
14
                        .parse::<i32>()
128
14
                        .unwrap();
129
14
                    ranges.push(Range::Single(*integer_value));
130
14
                }
131
931
                "int_range" => {
132
                    let lower_bound: Option<i32>;
133
                    let upper_bound: Option<i32>;
134
931
                    let range_component = int_range.child(0).expect("Error with integer range");
135
931
                    match range_component.kind() {
136
931
                        "expression" => {
137
931
                            lower_bound = Some(
138
931
                                source_code
139
931
                                    [range_component.start_byte()..range_component.end_byte()]
140
931
                                    .parse::<i32>()
141
931
                                    .unwrap(),
142
931
                            );
143

            
144
931
                            if let Some(range_component) = range_component.next_named_sibling() {
145
931
                                upper_bound = Some(
146
931
                                    source_code
147
931
                                        [range_component.start_byte()..range_component.end_byte()]
148
931
                                        .parse::<i32>()
149
931
                                        .unwrap(),
150
931
                                );
151
931
                            } else {
152
                                upper_bound = None;
153
                            }
154
                        }
155
                        ".." => {
156
                            lower_bound = None;
157
                            let range_component = range_component
158
                                .next_sibling()
159
                                .expect("Error with integer range");
160
                            upper_bound = Some(
161
                                source_code
162
                                    [range_component.start_byte()..range_component.end_byte()]
163
                                    .parse::<i32>()
164
                                    .unwrap(),
165
                            );
166
                        }
167
                        _ => panic!("unsupported int range type"),
168
                    }
169

            
170
931
                    match (lower_bound, upper_bound) {
171
931
                        (Some(lb), Some(ub)) => ranges.push(Range::Bounded(lb, ub)),
172
                        (Some(lb), None) => ranges.push(Range::Bounded(lb, std::i32::MAX)),
173
                        (None, Some(ub)) => ranges.push(Range::Bounded(std::i32::MIN, ub)),
174
                        _ => panic!("Unsupported int range type"),
175
                    }
176
                }
177
                _ => panic!("unsupported int range type"),
178
            }
179
        }
180
945
        Domain::IntDomain(ranges)
181
    }
182
945
}
183

            
184
42
fn parse_letting_statement(letting_statement_list: Node, source_code: &str) -> SymbolTable {
185
42
    let mut symbol_table = SymbolTable::new();
186

            
187
42
    for letting_statement in named_children(&letting_statement_list) {
188
42
        let mut temp_symbols = BTreeSet::new();
189
42

            
190
42
        let variable_list = letting_statement.child(0).expect("No variable list found");
191
42
        for variable in named_children(&variable_list) {
192
42
            let variable_name = &source_code[variable.start_byte()..variable.end_byte()];
193
42
            temp_symbols.insert(variable_name);
194
42
        }
195

            
196
42
        let expr_or_domain = letting_statement
197
42
            .named_child(1)
198
42
            .expect("No domain or expression found for letting statement");
199
42
        match expr_or_domain.kind() {
200
42
            "expression" => {
201
56
                for name in temp_symbols {
202
28
                    symbol_table.insert(Rc::new(Declaration::new_value_letting(
203
28
                        Name::UserName(String::from(name)),
204
28
                        parse_constraint(expr_or_domain, source_code),
205
28
                    )));
206
28
                }
207
            }
208
14
            "domain" => {
209
28
                for name in temp_symbols {
210
14
                    symbol_table.insert(Rc::new(Declaration::new_domain_letting(
211
14
                        Name::UserName(String::from(name)),
212
14
                        parse_domain(expr_or_domain, source_code),
213
14
                    )));
214
14
                }
215
            }
216
            _ => panic!("Unrecognized node in letting statement"),
217
        }
218
    }
219
42
    symbol_table
220
42
}
221

            
222
13797
fn parse_constraint(constraint: Node, source_code: &str) -> Expression {
223
13797
    match constraint.kind() {
224
13797
        "constraint" | "expression" => child_expr(constraint, source_code),
225
6489
        "not_expr" => Expression::Not(
226
133
            Metadata::new(),
227
133
            Box::new(child_expr(constraint, source_code)),
228
133
        ),
229
6356
        "abs_value" => Expression::Abs(
230
56
            Metadata::new(),
231
56
            Box::new(child_expr(constraint, source_code)),
232
56
        ),
233
6300
        "negative_expr" => Expression::Neg(
234
280
            Metadata::new(),
235
280
            Box::new(child_expr(constraint, source_code)),
236
280
        ),
237
6020
        "exponent" | "product_expr" | "sum_expr" | "comparison" | "and_expr" | "or_expr"
238
3878
        | "implication" => {
239
2408
            let expr1 = child_expr(constraint, source_code);
240
2408
            let op = constraint.child(1).unwrap_or_else(|| {
241
                panic!(
242
                    "Error: missing node in expression of kind {}",
243
                    constraint.kind()
244
                )
245
2408
            });
246
2408
            let op_type = &source_code[op.start_byte()..op.end_byte()];
247
2408
            let expr2_node = constraint.child(2).unwrap_or_else(|| {
248
                panic!(
249
                    "Error: missing node in expression of kind {}",
250
                    constraint.kind()
251
                )
252
2408
            });
253
2408
            let expr2 = parse_constraint(expr2_node, source_code);
254
2408

            
255
2408
            match op_type {
256
2408
                "**" => Expression::UnsafePow(Metadata::new(), Box::new(expr1), Box::new(expr2)),
257
2373
                "+" => Expression::Sum(Metadata::new(), vec![expr1, expr2]),
258
2030
                "-" => Expression::Minus(Metadata::new(), Box::new(expr1), Box::new(expr2)),
259
2002
                "*" => Expression::Product(Metadata::new(), vec![expr1, expr2]),
260
1855
                "/" => {
261
                    //TODO: add checks for if division is safe or not
262
259
                    Expression::UnsafeDiv(Metadata::new(), Box::new(expr1), Box::new(expr2))
263
                }
264
1596
                "%" => {
265
                    //TODO: add checks for if mod is safe or not
266
203
                    Expression::UnsafeMod(Metadata::new(), Box::new(expr1), Box::new(expr2))
267
                }
268
1393
                "=" => Expression::Eq(Metadata::new(), Box::new(expr1), Box::new(expr2)),
269
840
                "!=" => Expression::Neq(Metadata::new(), Box::new(expr1), Box::new(expr2)),
270
791
                "<=" => Expression::Leq(Metadata::new(), Box::new(expr1), Box::new(expr2)),
271
707
                ">=" => Expression::Geq(Metadata::new(), Box::new(expr1), Box::new(expr2)),
272
623
                "<" => Expression::Lt(Metadata::new(), Box::new(expr1), Box::new(expr2)),
273
476
                ">" => Expression::Gt(Metadata::new(), Box::new(expr1), Box::new(expr2)),
274
462
                "/\\" => Expression::And(Metadata::new(), vec![expr1, expr2]),
275
441
                "\\/" => Expression::Or(Metadata::new(), vec![expr1, expr2]),
276
266
                "->" => Expression::Imply(Metadata::new(), Box::new(expr1), Box::new(expr2)),
277
                _ => panic!("Error: unsupported operator"),
278
            }
279
        }
280
3612
        "quantifier_expr" => {
281
112
            let mut expr_list = Vec::new();
282
231
            for expr in named_children(&constraint) {
283
231
                expr_list.push(parse_constraint(expr, source_code));
284
231
            }
285

            
286
112
            let quantifier = constraint.child(0).unwrap_or_else(|| {
287
                panic!(
288
                    "Error: missing node in expression of kind {}",
289
                    constraint.kind()
290
                )
291
112
            });
292
112
            let quantifier_type = &source_code[quantifier.start_byte()..quantifier.end_byte()];
293
112

            
294
112
            match quantifier_type {
295
112
                "and" => Expression::And(Metadata::new(), expr_list),
296
112
                "or" => Expression::Or(Metadata::new(), expr_list),
297
105
                "min" => Expression::Min(Metadata::new(), expr_list),
298
56
                "max" => Expression::Max(Metadata::new(), expr_list),
299
35
                "sum" => Expression::Sum(Metadata::new(), expr_list),
300
14
                "allDiff" => Expression::AllDiff(Metadata::new(), expr_list),
301
                _ => panic!("Error: unsupported quantifier"),
302
            }
303
        }
304
3500
        "constant" => {
305
1386
            let child = constraint.child(0).unwrap_or_else(|| {
306
                panic!(
307
                    "Error: missing node in expression of kind {}",
308
                    constraint.kind()
309
                )
310
1386
            });
311
1386
            match child.kind() {
312
1386
                "integer" => {
313
1302
                    let constant_value = &source_code[child.start_byte()..child.end_byte()]
314
1302
                        .parse::<i32>()
315
1302
                        .unwrap();
316
1302
                    Expression::Atomic(
317
1302
                        Metadata::new(),
318
1302
                        Atom::Literal(Literal::Int(*constant_value)),
319
1302
                    )
320
                }
321
84
                "TRUE" => Expression::Atomic(Metadata::new(), Atom::Literal(Literal::Bool(true))),
322
28
                "FALSE" => Expression::Atomic(Metadata::new(), Atom::Literal(Literal::Bool(false))),
323
                _ => panic!("Error"),
324
            }
325
        }
326
2114
        "variable" => {
327
2114
            let variable_name =
328
2114
                String::from(&source_code[constraint.start_byte()..constraint.end_byte()]);
329
2114
            Expression::Atomic(
330
2114
                Metadata::new(),
331
2114
                Atom::Reference(Name::UserName(variable_name)),
332
2114
            )
333
        }
334
        _ => panic!("{} is not a recognized node kind", constraint.kind()),
335
    }
336
13797
}
337

            
338
4424
fn named_children<'a>(node: &'a Node<'a>) -> impl Iterator<Item = Node<'a>> + 'a {
339
7665
    (0..node.named_child_count()).filter_map(|i| node.named_child(i))
340
4424
}
341

            
342
10185
fn child_expr(node: Node, source_code: &str) -> Expression {
343
10185
    let child = node
344
10185
        .named_child(0)
345
10185
        .unwrap_or_else(|| panic!("Error: missing node in expression of kind {}", node.kind()));
346
10185
    parse_constraint(child, source_code)
347
10185
}