conjure_cp_essence_parser/parser/
parse_model.rs1use std::fs;
2use std::sync::{Arc, RwLock};
3
4use conjure_cp_core::Model;
5use conjure_cp_core::ast::Expression;
6use conjure_cp_core::ast::{DeclarationPtr, Moo};
7use conjure_cp_core::context::Context;
8use conjure_cp_core::error::Error;
9use conjure_cp_core::metadata::Metadata;
10#[allow(unused)]
11use uniplate::Uniplate;
12
13use crate::errors::EssenceParseError;
14
15use super::expression::parse_expression;
16use super::find::parse_find_statement;
17use super::letting::parse_letting_statement;
18use super::util::{get_tree, named_children};
19
20pub fn parse_essence_file_native(
22 path: &str,
23 context: Arc<RwLock<Context<'static>>>,
24) -> Result<Model, EssenceParseError> {
25 let source_code = fs::read_to_string(path)
26 .unwrap_or_else(|_| panic!("Failed to read the source code file {path}"));
27 parse_essence_with_context(&source_code, context)
28}
29
30pub fn parse_essence_with_context(
31 src: &str,
32 context: Arc<RwLock<Context<'static>>>,
33) -> Result<Model, EssenceParseError> {
34 let (tree, source_code) = match get_tree(src) {
35 Some(tree) => tree,
36 None => {
37 return Err(EssenceParseError::TreeSitterError(
38 "Failed to parse source code".to_string(),
39 ));
40 }
41 };
42
43 let mut model = Model::new(context);
44 let root_node = tree.root_node();
46 for statement in named_children(&root_node) {
47 match statement.kind() {
48 "single_line_comment" => {}
49 "find_statement_list" => {
50 let var_hashmap = parse_find_statement(statement, &source_code);
51 for (name, domain) in var_hashmap {
52 model
53 .as_submodel_mut()
54 .symbols_mut()
55 .insert(DeclarationPtr::new_var(name, domain));
56 }
57 }
58 "constraint_list" => {
59 let mut constraint_vec: Vec<Expression> = Vec::new();
60 for constraint in named_children(&statement) {
61 let current_symbols = model.as_submodel().symbols().clone();
62
63 if constraint.kind() != "single_line_comment" {
64 constraint_vec.push(parse_expression(
65 constraint,
66 &source_code,
67 &statement,
68 ¤t_symbols,
69 )?);
70 }
71 }
72 model.as_submodel_mut().add_constraints(constraint_vec);
73 }
74 "language_label" => {}
75 "letting_statement_list" => {
76 let letting_vars = parse_letting_statement(statement, &source_code)?;
77 model.as_submodel_mut().symbols_mut().extend(letting_vars);
78 }
79 "dominance_relation" => {
80 let inner = statement
81 .child(1)
82 .expect("Expected a sub-expression inside `dominanceRelation`");
83 let current_symbols = model.as_submodel().symbols().clone();
84 let expr = parse_expression(inner, &source_code, &statement, ¤t_symbols)?;
85 let dominance = Expression::DominanceRelation(Metadata::new(), Moo::new(expr));
86 if model.dominance.is_some() {
87 return Err(EssenceParseError::ParseError(Error::Parse(
88 "Duplicate dominance relation".to_owned(),
89 )));
90 }
91 model.dominance = Some(dominance);
92 }
93 _ => {
94 let kind = statement.kind();
95 return Err(EssenceParseError::ParseError(Error::Parse(format!(
96 "Unrecognized top level statement kind: {kind}"
97 ))));
98 }
99 }
100 }
101 Ok(model)
102}