conjure_cp_essence_parser/parser/
parse_exprs.rs1use super::ParseContext;
2use super::util::{get_expr_tree, query_toplevel};
3use crate::diagnostics::source_map::SourceMap;
4use crate::errors::FatalParseError;
5use crate::expression::parse_expression;
6use crate::util::TypecheckingContext;
7use crate::util::node_is_expression;
8use conjure_cp_core::ast::{Expression, SymbolTablePtr};
9use std::collections::BTreeMap;
10#[allow(unused)]
11use uniplate::Uniplate;
12
13pub fn parse_expr(
14 src: &str,
15 symbols_ptr: SymbolTablePtr,
16) -> Result<Option<Expression>, FatalParseError> {
17 let exprs = parse_exprs(src, symbols_ptr)?;
18 if exprs.len() != 1 {
19 return Ok(None);
20 }
21 Ok(Some(exprs[0].clone()))
22}
23
24pub fn parse_exprs(
25 src: &str,
26 symbols_ptr: SymbolTablePtr,
27) -> Result<Vec<Expression>, FatalParseError> {
28 let Some((tree, source_code)) = get_expr_tree(src) else {
29 return Ok(Vec::new());
30 };
31
32 let root = tree.root_node();
33 let mut source_map = SourceMap::default();
34 let mut decl_spans = BTreeMap::new();
35 let mut errors = Vec::new();
36 let mut ctx = ParseContext::new(
37 &source_code,
38 &root,
39 Some(symbols_ptr),
40 &mut errors,
41 &mut source_map,
42 &mut decl_spans,
43 );
44 let mut ans = Vec::new();
45 for expr in query_toplevel(&root, &node_is_expression) {
46 ctx.typechecking_context = TypecheckingContext::Unknown;
47 ctx.inner_typechecking_context = TypecheckingContext::Unknown;
48 let Some(expr) = parse_expression(&mut ctx, expr)? else {
49 continue;
50 };
51 ans.push(expr);
52 }
53 Ok(ans)
54}
55
56mod test {
57 #[allow(unused)]
58 use super::{parse_expr, parse_exprs};
59 #[allow(unused)]
60 use conjure_cp_core::ast::SymbolTablePtr;
61 #[allow(unused)]
62 use conjure_cp_core::ast::{
63 Atom, DeclarationPtr, Domain, Expression, Literal, Metadata, Moo, Name, SymbolTable,
64 };
65 #[allow(unused)]
66 use std::collections::HashMap;
67 #[allow(unused)]
68 use std::sync::Arc;
69 #[allow(unused)]
70 use tree_sitter::Range;
71
72 #[test]
73 pub fn test_parse_constant() {
74 let symbols = SymbolTablePtr::new();
75
76 assert_eq!(
77 parse_expr("42", symbols.clone()).unwrap().unwrap(),
78 Expression::Atomic(Metadata::new(), Atom::Literal(Literal::Int(42)))
79 );
80 assert_eq!(
81 parse_expr("true", symbols.clone()).unwrap().unwrap(),
82 Expression::Atomic(Metadata::new(), Atom::Literal(Literal::Bool(true)))
83 );
84 assert_eq!(
85 parse_expr("false", symbols).unwrap().unwrap(),
86 Expression::Atomic(Metadata::new(), Atom::Literal(Literal::Bool(false)))
87 )
88 }
89
90 #[test]
91 pub fn test_parse_expressions() {
92 let src = "x >= 5, y = a / 2";
93 let symbols = SymbolTablePtr::new();
94 let x = DeclarationPtr::new_find(
95 Name::User("x".into()),
96 Domain::int(vec![conjure_cp_core::ast::Range::Bounded(0, 10)]),
97 );
98
99 let y = DeclarationPtr::new_find(
100 Name::User("y".into()),
101 Domain::int(vec![conjure_cp_core::ast::Range::Bounded(0, 10)]),
102 );
103
104 let a = DeclarationPtr::new_find(
105 Name::User("a".into()),
106 Domain::int(vec![conjure_cp_core::ast::Range::Bounded(0, 10)]),
107 );
108
109 symbols
111 .write()
112 .insert(x.clone())
113 .expect("x should not exist in the symbol-table yet, so we should be able to add it");
114
115 symbols
116 .write()
117 .insert(y.clone())
118 .expect("y should not exist in the symbol-table yet, so we should be able to add it");
119
120 symbols
121 .write()
122 .insert(a.clone())
123 .expect("a should not exist in the symbol-table yet, so we should be able to add it");
124
125 let exprs = parse_exprs(src, symbols).unwrap();
126 assert_eq!(exprs.len(), 2);
127
128 assert_eq!(
129 exprs[0],
130 Expression::Geq(
131 Metadata::new(),
132 Moo::new(Expression::Atomic(Metadata::new(), Atom::new_ref(x))),
133 Moo::new(Expression::Atomic(Metadata::new(), 5.into()))
134 )
135 );
136
137 assert_eq!(
138 exprs[1],
139 Expression::Eq(
140 Metadata::new(),
141 Moo::new(Expression::Atomic(Metadata::new(), Atom::new_ref(y))),
142 Moo::new(Expression::UnsafeDiv(
143 Metadata::new(),
144 Moo::new(Expression::Atomic(Metadata::new(), Atom::new_ref(a))),
145 Moo::new(Expression::Atomic(Metadata::new(), 2.into()))
146 ))
147 )
148 );
149 }
150}