xcsp3_serde/
expression.rs

1//! # Expressions for constraints and objectives
2//!
3//! This module defines the expressions used in constraints and objectives.
4//! These expressions are represented in textual format in the XCSP3 XML format.
5//! The expressions are parsed from strings and can be serialized back to
6//! strings.
7//!
8//! The expressions are generally split using the type of value or decision
9//! variable it will result in. An enumerated type [`Exp`] is used to represent
10//! expressions in positions that could take multiple or any type.
11
12use std::{fmt::Display, marker::PhantomData, ops::RangeInclusive, str::FromStr};
13
14use nom::{
15	branch::alt,
16	bytes::complete::tag,
17	character::complete::{alphanumeric1, char, digit1, multispace0, multispace1},
18	combinator::{all_consuming, map, map_res, opt, recognize, verify},
19	multi::{many0, separated_list0, separated_list1},
20	sequence::{delimited, pair, preceded, separated_pair, terminated},
21	IResult, Parser,
22};
23use serde::{de::Visitor, Deserialize, Deserializer, Serialize, Serializer};
24
25use crate::{IntVal, VarRef};
26
27/// List of reserved identifiers used by builtin expressions
28pub const RESERVED: &[&str] = &[
29	"abs", "add", "and", "card", "convex", "diff", "disjoint", "dist", "div", "eq", "ge", "gt",
30	"hull", "if", "iff", "imp", "in", "inter", "le", "lt", "max", "min", "mod", "mul", "ne", "neg",
31	"not", "or", "pow", "sdiff", "set", "sqr", "sqrt", "sub", "subseq", "subset", "superseq",
32	"superset", "union", "xor",
33];
34
35/// Expression resulting in a Boolean value or decision variable
36#[derive(Clone, Debug, PartialEq, Hash)]
37pub enum BoolExp<Identifier> {
38	/// Boolean constant
39	///
40	/// When serialized Boolean values `false` and `true` are represented by
41	/// integer values 0 and 1.
42	Const(bool),
43	/// Reference to a variable or array access
44	Var(VarRef<Identifier>),
45	/// Logical not (i.e., ¬x)
46	Not(Box<BoolExp<Identifier>>),
47	/// Logical and (i.e., x1 ∧ ...∧ xn)
48	And(Vec<BoolExp<Identifier>>),
49	/// Logical or (i.e., x1 ∨ ... ∨ xn)
50	Or(Vec<BoolExp<Identifier>>),
51	/// Logical xor (i.e., x1 ⊕ ... ⊕ xn)
52	Xor(Vec<BoolExp<Identifier>>),
53	/// Logical equivalence (i.e., x1 ⇔ ... ⇔ xn)
54	Equiv(Vec<BoolExp<Identifier>>),
55	/// Logical implication (i.e., x ⇒ y)
56	Implies(Box<BoolExp<Identifier>>, Box<BoolExp<Identifier>>),
57	/// Less than (i.e., x < y)
58	LessThan(Box<IntExp<Identifier>>, Box<IntExp<Identifier>>),
59	/// Less than or equal (i.e., x ≤ y)
60	LessThanEq(Box<IntExp<Identifier>>, Box<IntExp<Identifier>>),
61	///Greater than (i.e., x > y)
62	GreaterThan(Box<IntExp<Identifier>>, Box<IntExp<Identifier>>),
63	///Greater than or equal (i.e., x ≥ y)
64	GreaterThanEq(Box<IntExp<Identifier>>, Box<IntExp<Identifier>>),
65	/// Different From (i.e., x ≠ y)
66	NotEqual(Box<Exp<Identifier>>, Box<Exp<Identifier>>),
67	/// Equal to (i.e., x1 = ... = xr)
68	Equal(Vec<Exp<Identifier>>),
69	/// Membership (i.e., x ∈ s)
70	Member(Box<IntExp<Identifier>>, Box<SetExp<Identifier>>),
71	/// Disjoint sets (i.e., s ∩ t = ∅)
72	Disjoint(Box<SetExp<Identifier>>, Box<SetExp<Identifier>>),
73	/// Strict subset (i.e., s ⊂ t)
74	SubSet(Box<SetExp<Identifier>>, Box<SetExp<Identifier>>),
75	/// Subset or equal to (i.e., s ⊆ t)
76	SubSetEq(Box<SetExp<Identifier>>, Box<SetExp<Identifier>>),
77	/// Strict superset (i.e., s ⊃ t)
78	SuperSet(Box<SetExp<Identifier>>, Box<SetExp<Identifier>>),
79	/// Superset or equal to (i.e., s ⊇ t)
80	SuperSetEq(Box<SetExp<Identifier>>, Box<SetExp<Identifier>>),
81	/// Convexity (i.e., s = {i : min s ≤ i ≤ max s})
82	Convex(Box<SetExp<Identifier>>),
83}
84
85/// Expression of any type
86#[derive(Clone, Debug, PartialEq, Hash)]
87pub enum Exp<Identifier> {
88	/// A Boolean expression
89	Bool(Box<BoolExp<Identifier>>),
90	/// An integer expression
91	Int(Box<IntExp<Identifier>>),
92	/// An set of integers expression
93	Set(Box<SetExp<Identifier>>),
94	/// Reference to a variable or array access
95	Var(VarRef<Identifier>),
96}
97
98/// Expression resulting in an integer value or decision variable
99#[derive(Clone, Debug, PartialEq, Hash)]
100pub enum IntExp<Identifier> {
101	/// Constant integer value
102	Const(IntVal),
103	/// Reference to a variable or array access
104	Var(VarRef<Identifier>),
105	/// Oposite (i.e., -x)
106	Neg(Box<IntExp<Identifier>>),
107	/// Absolute value (i.e., |x|)
108	Abs(Box<IntExp<Identifier>>),
109	/// Addition (i.e., x1 + ... + xn)
110	Add(Vec<IntExp<Identifier>>),
111	/// Subtraction (i.e., x - y)
112	Sub(Box<IntExp<Identifier>>, Box<IntExp<Identifier>>),
113	/// Multiplication (i.e., x1 ∗ ... ∗ xn)
114	Mul(Vec<IntExp<Identifier>>),
115	/// Division (i.e., x / y)
116	Div(Box<IntExp<Identifier>>, Box<IntExp<Identifier>>),
117	/// Remainder (i.e., x % y)
118	Mod(Box<IntExp<Identifier>>, Box<IntExp<Identifier>>),
119	/// Square (i.e., x^2)
120	Sqr(Box<IntExp<Identifier>>),
121	/// Power (i.e., x^y)
122	Pow(Box<IntExp<Identifier>>, Box<IntExp<Identifier>>),
123	/// Minimum (i.e., min{x1, ..., xn})
124	Min(Vec<Exp<Identifier>>),
125	/// Maximum (i.e., max{x1, ..., xn})
126	Max(Vec<Exp<Identifier>>),
127	/// Distance (i.e., |x - y|)
128	Dist(Box<IntExp<Identifier>>, Box<IntExp<Identifier>>),
129	/// Alternative (i.e., value of x, if b is true, value of y, otherwise)
130	If(
131		BoolExp<Identifier>,
132		Box<IntExp<Identifier>>,
133		Box<IntExp<Identifier>>,
134	),
135	/// Boolean expression used as an integer expression
136	Bool(BoolExp<Identifier>),
137	/// Cardinality (i.e., |s|)
138	Card(Box<SetExp<Identifier>>),
139}
140
141/// Expression resulting in an set of integers value or decision variable
142#[derive(Clone, Debug, PartialEq, Hash)]
143pub enum SetExp<Identifier> {
144	/// Set literal specifying each of its values (i.e., {x1, ..., xn})
145	Set(Vec<IntExp<Identifier>>),
146	/// Set literal specifying an inclusive range using a lower and upper bound
147	/// (i.e., { i : x ≤ i ≤ y})
148	Range((IntExp<Identifier>, IntExp<Identifier>)),
149	/// Reference to a variable or array access
150	Var(VarRef<Identifier>),
151	/// Convex hull (i.e., {i : min s ≤ i ≤ max s})
152	Hull(Box<SetExp<Identifier>>),
153	/// Difference (i.e., s \ t)
154	Diff(Box<SetExp<Identifier>>, Box<SetExp<Identifier>>),
155	/// Union (i.e., s1 ∪ ... ∪ sn)
156	Union(Vec<SetExp<Identifier>>),
157	/// Intersection (i.e., s1 ∩ ... ∩ sn)
158	Inter(Vec<SetExp<Identifier>>),
159	/// Symmetric difference (i.e., s1 ∆ ... ∆ sn)
160	SDiff(Vec<SetExp<Identifier>>),
161}
162
163/// Parser combinator that parses an identifier from a string
164pub(crate) fn identifier<Identifier: FromStr>(input: &str) -> IResult<&str, Identifier> {
165	let (input, v) = verify(alphanumeric1, |s: &str| {
166		s.chars().next().unwrap().is_ascii_alphabetic() && !RESERVED.contains(&s)
167	})
168	.parse(input)?;
169	Ok((
170		input,
171		match v.parse() {
172			Ok(t) => t,
173			Err(_) => panic!("unable to create identifier"),
174		},
175	))
176}
177
178/// Parser combinator that parses an integer from a string
179pub(crate) fn int(input: &str) -> IResult<&str, IntVal> {
180	let (input, neg) = opt(char('-')).parse(input)?;
181	let (input, i): (_, i64) = map_res(recognize(digit1), str::parse).parse(input)?;
182	Ok((input, if neg.is_some() { -i } else { i }))
183}
184
185/// Parser combinator that parses a range of integers from a string
186pub(crate) fn range(input: &str) -> IResult<&str, RangeInclusive<IntVal>> {
187	let (input, lb) = int(input)?;
188	if let (input, Some(_)) = opt(tag("..")).parse(input)? {
189		let (input, ub) = int(input)?;
190		Ok((input, lb..=ub))
191	} else {
192		Ok((input, lb..=lb))
193	}
194}
195
196/// Parser combinator that repeatedly calls a parser consuming whitespace in
197/// between when possible
198pub(crate) fn sequence<'a, O>(
199	p: impl Parser<&'a str, Output = O>,
200) -> impl Parser<&'a str, Output = Vec<O>> {
201	terminated(many0(preceded(multispace0, p)), multispace0)
202}
203
204/// Parser combinator that expects parentheses with a comma seperated parser
205/// rules
206pub(crate) fn tuple<'a, O>(
207	p: impl Parser<&'a str, Output = O>,
208) -> impl Parser<&'a str, Output = Vec<O>> {
209	delimited(char('('), separated_list1(char(','), p), char(')'))
210}
211
212/// Parser combinator that requires whitespace between parsing rules
213pub(crate) fn whitespace_seperated<'a, O>(
214	p: impl Parser<&'a str, Output = O>,
215) -> impl Parser<&'a str, Output = Vec<O>> {
216	separated_list1(multispace1, p)
217}
218
219impl<Identifier: FromStr> BoolExp<Identifier> {
220	/// Parser combinator for a call Boolean expression with a Boolean argument
221	/// from a string.
222	fn call_arg1(input: &str) -> IResult<&str, Self> {
223		let (input, tag) = tag("not")(input)?;
224		let (input, _) = char('(')(input)?;
225		let (input, e) = Self::parse(input)?;
226		let (input, _) = char(')')(input)?;
227		Ok((
228			input,
229			match tag {
230				"not" => BoolExp::Not,
231				_ => unreachable!(),
232			}(Box::new(e)),
233		))
234	}
235
236	/// Parser combinator for a call Boolean expression with a set arguments from
237	/// a string.
238	fn call_arg1_set(input: &str) -> IResult<&str, Self> {
239		let (input, tag) = tag("convex")(input)?;
240		let (input, _) = char('(')(input)?;
241		let (input, e) = SetExp::parse(input)?;
242		let (input, _) = char(')')(input)?;
243		Ok((
244			input,
245			match tag {
246				"convex" => BoolExp::Convex,
247				_ => unreachable!(),
248			}(Box::new(e)),
249		))
250	}
251
252	/// Parser combinator for a call Boolean expression with two Boolean arguments
253	/// from a string.
254	fn call_arg2(input: &str) -> IResult<&str, Self> {
255		let (input, tag) = tag("imp")(input)?;
256		let (input, _) = char('(')(input)?;
257		let (input, e1) = Self::parse(input)?;
258		let (input, _) = char(',')(input)?;
259		let (input, e2) = Self::parse(input)?;
260		let (input, _) = char(')')(input)?;
261		Ok((
262			input,
263			match tag {
264				"imp" => BoolExp::Implies,
265				_ => unreachable!(),
266			}(Box::new(e1), Box::new(e2)),
267		))
268	}
269
270	/// Parser combinator for a call Boolean expression with two expression
271	/// arguments from a string.
272	fn call_arg2_exp(input: &str) -> IResult<&str, Self> {
273		let (input, tag) = tag("ne")(input)?;
274		let (input, _) = char('(')(input)?;
275		let (input, e1) = Exp::parse(input)?;
276		let (input, _) = char(',')(input)?;
277		let (input, e2) = Exp::parse(input)?;
278		let (input, _) = char(')')(input)?;
279		Ok((
280			input,
281			match tag {
282				"imp" => BoolExp::NotEqual,
283				_ => unreachable!(),
284			}(Box::new(e1), Box::new(e2)),
285		))
286	}
287
288	/// Parser combinator for a call Boolean expression with two integer arguments
289	/// from a string.
290	fn call_arg2_int(input: &str) -> IResult<&str, Self> {
291		let (input, tag) = alt((tag("lt"), tag("le"), tag("gt"), tag("ge"))).parse(input)?;
292		let (input, _) = char('(')(input)?;
293		let (input, e1) = IntExp::parse(input)?;
294		let (input, _) = char(',')(input)?;
295		let (input, e2) = IntExp::parse(input)?;
296		let (input, _) = char(')')(input)?;
297		Ok((
298			input,
299			match tag {
300				"lt" => BoolExp::LessThan,
301				"le" => BoolExp::LessThanEq,
302				"gt" => BoolExp::GreaterThan,
303				"ge" => BoolExp::GreaterThanEq,
304				_ => unreachable!(),
305			}(Box::new(e1), Box::new(e2)),
306		))
307	}
308
309	/// Parser combinator for a call Boolean expression with an integer and a set
310	/// argument from a string.
311	fn call_arg2_int_set(input: &str) -> IResult<&str, Self> {
312		let (input, tag) = tag("in")(input)?;
313		let (input, _) = char('(')(input)?;
314		let (input, e1) = IntExp::parse(input)?;
315		let (input, _) = char(',')(input)?;
316		let (input, e2) = SetExp::parse(input)?;
317		let (input, _) = char(')')(input)?;
318		Ok((
319			input,
320			match tag {
321				"in" => BoolExp::Member,
322				_ => unreachable!(),
323			}(Box::new(e1), Box::new(e2)),
324		))
325	}
326
327	/// Parser combinator for a call Boolean expression with two set arguments
328	/// from a string.
329	fn call_arg2_set(input: &str) -> IResult<&str, Self> {
330		let (input, tag) = alt((
331			tag("disjoint"),
332			tag("subset"),
333			tag("subseq"),
334			tag("supseq"),
335			tag("supset"),
336		))
337		.parse(input)?;
338		let (input, _) = char('(')(input)?;
339		let (input, e1) = SetExp::parse(input)?;
340		let (input, _) = char(',')(input)?;
341		let (input, e2) = SetExp::parse(input)?;
342		let (input, _) = char(')')(input)?;
343		Ok((
344			input,
345			match tag {
346				"disjoint" => BoolExp::Disjoint,
347				"subset" => BoolExp::SubSet,
348				"subseq" => BoolExp::SubSetEq,
349				"supseq" => BoolExp::SuperSetEq,
350				"supset" => BoolExp::SuperSet,
351				_ => unreachable!(),
352			}(Box::new(e1), Box::new(e2)),
353		))
354	}
355
356	/// Parser combinator for a call Boolean expression with a variadic number of
357	/// Boolean arguments from a string.
358	fn call_argn(input: &str) -> IResult<&str, Self> {
359		let (input, tag) = alt((tag("and"), tag("or"), tag("xor"), tag("iff"))).parse(input)?;
360		let (input, _) = char('(')(input)?;
361		let (input, es) = separated_list0(char(','), Self::parse).parse(input)?;
362		let (input, _) = char(')')(input)?;
363		Ok((
364			input,
365			match tag {
366				"and" => BoolExp::And,
367				"or" => BoolExp::Or,
368				"xor" => BoolExp::Xor,
369				"iff" => BoolExp::Equiv,
370				_ => unreachable!(),
371			}(es),
372		))
373	}
374
375	/// Parser combinator for a call Boolean expression with a variadic number of
376	/// expression arguments from a string.
377	fn call_argn_exp(input: &str) -> IResult<&str, Self> {
378		let (input, tag) = tag("eq")(input)?;
379		let (input, _) = char('(')(input)?;
380		let (input, es) = separated_list1(char(','), Exp::parse).parse(input)?;
381		let (input, _) = char(')')(input)?;
382		Ok((
383			input,
384			match tag {
385				"eq" => BoolExp::Equal,
386				_ => unreachable!(),
387			}(es),
388		))
389	}
390
391	/// Parser combinator for a Boolean expression from a string.
392	pub(crate) fn parse(input: &str) -> IResult<&str, Self> {
393		alt((
394			map(verify(digit1, |s| matches!(s, "0" | "1")), |s| {
395				BoolExp::Const(s == "1")
396			}),
397			Self::call_arg1,
398			Self::call_arg1_set,
399			Self::call_arg2,
400			Self::call_arg2_int,
401			Self::call_arg2_int_set,
402			Self::call_arg2_set,
403			Self::call_arg2_exp,
404			Self::call_argn,
405			Self::call_argn_exp,
406			map(VarRef::parse, BoolExp::Var),
407		))
408		.parse(input)
409	}
410}
411
412impl<'de, Identifier: FromStr> Deserialize<'de> for BoolExp<Identifier> {
413	fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<BoolExp<Identifier>, D::Error> {
414		/// Visitor for deserializing a `BoolExp`.
415		struct V<Ident>(PhantomData<Ident>);
416		impl<Ident: FromStr> Visitor<'_> for V<Ident> {
417			type Value = BoolExp<Ident>;
418
419			fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
420				formatter.write_str("a Boolean expression")
421			}
422
423			fn visit_str<E: serde::de::Error>(self, v: &str) -> Result<Self::Value, E> {
424				let v = v.trim();
425				let (_, v) = Self::Value::parse(v)
426					.map_err(|e| E::custom(format!("invalid Boolean expression: {e:?}")))?;
427				Ok(v)
428			}
429		}
430		deserializer.deserialize_str(V(PhantomData::<Identifier>))
431	}
432}
433
434impl<Identifier: Display> Display for BoolExp<Identifier> {
435	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
436		match self {
437			BoolExp::Const(b) => write!(f, "{}", if *b { 1 } else { 0 }),
438			BoolExp::Var(id) => write!(f, "{}", id),
439			BoolExp::Not(e) => write!(f, "not({})", e),
440			BoolExp::And(es) => write!(
441				f,
442				"and({})",
443				es.iter()
444					.map(|e| e.to_string())
445					.collect::<Vec<_>>()
446					.join(",")
447			),
448			BoolExp::Or(es) => write!(
449				f,
450				"or({})",
451				es.iter()
452					.map(|e| e.to_string())
453					.collect::<Vec<_>>()
454					.join(",")
455			),
456			BoolExp::Xor(es) => write!(
457				f,
458				"xor({})",
459				es.iter()
460					.map(|e| e.to_string())
461					.collect::<Vec<_>>()
462					.join(",")
463			),
464			BoolExp::Equiv(es) => write!(
465				f,
466				"iff({})",
467				es.iter()
468					.map(|e| e.to_string())
469					.collect::<Vec<_>>()
470					.join(",")
471			),
472			BoolExp::Implies(e1, e2) => write!(f, "imp({},{})", e1, e2),
473			BoolExp::LessThan(e1, e2) => write!(f, "lt({},{})", e1, e2),
474			BoolExp::LessThanEq(e1, e2) => write!(f, "le({},{})", e1, e2),
475			BoolExp::GreaterThan(e1, e2) => write!(f, "gt({},{})", e1, e2),
476			BoolExp::GreaterThanEq(e1, e2) => write!(f, "ge({},{})", e1, e2),
477			BoolExp::NotEqual(e1, e2) => write!(f, "ne({},{})", e1, e2),
478			BoolExp::Equal(es) => write!(
479				f,
480				"eq({})",
481				es.iter()
482					.map(|e| e.to_string())
483					.collect::<Vec<_>>()
484					.join(",")
485			),
486			BoolExp::Member(e1, e2) => write!(f, "in({},{})", e1, e2),
487			BoolExp::Disjoint(e1, e2) => write!(f, "disjoint({},{})", e1, e2),
488			BoolExp::SubSet(e1, e2) => write!(f, "subset({},{})", e1, e2),
489			BoolExp::SubSetEq(e1, e2) => write!(f, "subseq({},{})", e1, e2),
490			BoolExp::SuperSet(e1, e2) => write!(f, "supset({},{})", e1, e2),
491			BoolExp::SuperSetEq(e1, e2) => write!(f, "supseq({},{})", e1, e2),
492			BoolExp::Convex(e) => write!(f, "convex({})", e),
493		}
494	}
495}
496
497impl<Identifier: Display> Serialize for BoolExp<Identifier> {
498	fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
499		serializer.serialize_str(&self.to_string())
500	}
501}
502
503impl<Identifier: FromStr> Exp<Identifier> {
504	/// Parser combinator for an expression of any type from a string
505	pub(crate) fn parse(input: &str) -> IResult<&str, Self> {
506		alt((
507			map(VarRef::parse, |x| Exp::Var(x)),
508			map(SetExp::parse, |x| Exp::Set(Box::new(x))),
509			map(BoolExp::parse, |x| Exp::Bool(Box::new(x))),
510			map(IntExp::parse, |x| Exp::Int(Box::new(x))),
511		))
512		.parse(input)
513	}
514
515	/// Parse a list of expressions seperated by whitespace
516	pub(crate) fn parse_vec<'de, D: Deserializer<'de>>(
517		deserializer: D,
518	) -> Result<Vec<Self>, D::Error> {
519		/// Visitor for parsing a list of expressions
520		struct V<X>(PhantomData<X>);
521		impl<X: FromStr> Visitor<'_> for V<X> {
522			type Value = Vec<Exp<X>>;
523
524			fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
525				formatter.write_str("a list of expressions")
526			}
527
528			fn visit_str<E: serde::de::Error>(self, v: &str) -> Result<Self::Value, E> {
529				let v = v.trim();
530				let (_, v) = all_consuming(whitespace_seperated(Exp::parse))
531					.parse(v)
532					.map_err(|_| E::custom(format!("invalid expressions `{v}'")))?;
533				Ok(v)
534			}
535		}
536		let visitor = V::<Identifier>(PhantomData);
537		deserializer.deserialize_str(visitor)
538	}
539}
540
541impl<Identifier: Display> Display for Exp<Identifier> {
542	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
543		match self {
544			Exp::Bool(e) => write!(f, "{}", e),
545			Exp::Int(e) => write!(f, "{}", e),
546			Exp::Set(e) => write!(f, "{}", e),
547			Exp::Var(e) => write!(f, "{}", e),
548		}
549	}
550}
551
552impl<Identifier: FromStr> IntExp<Identifier> {
553	/// Parser combinator for a call integer expression with a integer argument
554	/// from string
555	fn call_arg1(input: &str) -> IResult<&str, Self> {
556		let (input, tag) = alt((tag("neg"), tag("abs"), tag("sqr"))).parse(input)?;
557		let (input, _) = char('(')(input)?;
558		let (input, e) = Self::parse(input)?;
559		let (input, _) = char(')')(input)?;
560		Ok((
561			input,
562			match tag {
563				"neg" => IntExp::Neg,
564				"abs" => IntExp::Abs,
565				"sqr" => IntExp::Sqr,
566				_ => unreachable!(),
567			}(Box::new(e)),
568		))
569	}
570
571	/// Parser combinator for a call integer expression with a set argument from
572	/// string
573	fn call_arg1_set(input: &str) -> IResult<&str, Self> {
574		let (input, tag) = tag("card")(input)?;
575		let (input, _) = char('(')(input)?;
576		let (input, e) = SetExp::parse(input)?;
577		let (input, _) = char(')')(input)?;
578		Ok((
579			input,
580			match tag {
581				"card" => IntExp::Card,
582				_ => unreachable!(),
583			}(Box::new(e)),
584		))
585	}
586
587	/// Parser combinator for a call integer expression with two integer arguments
588	/// from string
589	fn call_arg2(input: &str) -> IResult<&str, Self> {
590		let (input, tag) =
591			alt((tag("sub"), tag("div"), tag("mod"), tag("pow"), tag("dist"))).parse(input)?;
592		let (input, _) = char('(')(input)?;
593		let (input, e1) = Self::parse(input)?;
594		let (input, _) = char(',')(input)?;
595		let (input, e2) = Self::parse(input)?;
596		let (input, _) = char(')')(input)?;
597		Ok((
598			input,
599			match tag {
600				"sub" => IntExp::Sub,
601				"div" => IntExp::Div,
602				"mod" => IntExp::Mod,
603				"pow" => IntExp::Pow,
604				"dist" => IntExp::Dist,
605				_ => unreachable!(),
606			}(Box::new(e1), Box::new(e2)),
607		))
608	}
609
610	/// Parser combinator for a call integer expression with three integer
611	/// arguments from string
612	fn call_arg3(input: &str) -> IResult<&str, Self> {
613		let (input, tag) = alt((tag("if"),)).parse(input)?;
614		let (input, _) = char('(')(input)?;
615		let (input, e1) = BoolExp::parse(input)?;
616		let (input, _) = char(',')(input)?;
617		let (input, e2) = Self::parse(input)?;
618		let (input, _) = char(',')(input)?;
619		let (input, e3) = Self::parse(input)?;
620		let (input, _) = char(')')(input)?;
621		Ok((
622			input,
623			match tag {
624				"if" => IntExp::If,
625				_ => unreachable!(),
626			}(e1, Box::new(e2), Box::new(e3)),
627		))
628	}
629
630	/// Parser combinator for a call integer expression with variadic number of
631	/// integer arguments from string
632	fn call_argn(input: &str) -> IResult<&str, Self> {
633		let (input, tag) = alt((tag("add"), tag("mul"))).parse(input)?;
634		let (input, _) = char('(')(input)?;
635		let (input, es) = separated_list1(char(','), Self::parse).parse(input)?;
636		let (input, _) = char(')')(input)?;
637		Ok((
638			input,
639			match tag {
640				"add" => IntExp::Add,
641				"mul" => IntExp::Mul,
642				_ => unreachable!(),
643			}(es),
644		))
645	}
646
647	/// Parser combinator for a call integer expression with variadic number of
648	/// expression arguments from string
649	fn call_argn_exp(input: &str) -> IResult<&str, Self> {
650		let (input, tag) = alt((tag("min"), tag("max"))).parse(input)?;
651		let (input, _) = char('(')(input)?;
652		let (input, es) = separated_list1(char(','), Exp::parse).parse(input)?;
653		let (input, _) = char(')')(input)?;
654		Ok((
655			input,
656			match tag {
657				"min" => IntExp::Min,
658				"max" => IntExp::Max,
659				_ => unreachable!(),
660			}(es),
661		))
662	}
663
664	/// Parser combinator for an integer expression from string
665	pub(crate) fn parse(input: &str) -> IResult<&str, Self> {
666		alt((
667			map(int, IntExp::Const),
668			IntExp::call_arg1,
669			IntExp::call_arg1_set,
670			IntExp::call_arg2,
671			IntExp::call_arg3,
672			IntExp::call_argn,
673			IntExp::call_argn_exp,
674			map(VarRef::parse, IntExp::Var),
675			map(BoolExp::parse, IntExp::Bool),
676		))
677		.parse(input)
678	}
679
680	/// Parse a list of integer expressions
681	pub(crate) fn parse_vec<'de, D: Deserializer<'de>>(
682		deserializer: D,
683	) -> Result<Vec<Self>, D::Error> {
684		/// Visitor for a list of integer expressions
685		struct V<X>(PhantomData<X>);
686		impl<X: FromStr> Visitor<'_> for V<X> {
687			type Value = Vec<IntExp<X>>;
688
689			fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
690				formatter.write_str("a list of integers expressions")
691			}
692
693			fn visit_str<E: serde::de::Error>(self, v: &str) -> Result<Self::Value, E> {
694				let v = v.trim();
695				let (_, v) = all_consuming(whitespace_seperated(IntExp::parse))
696					.parse(v)
697					.map_err(|_| E::custom(format!("invalid integer expressions `{v}'")))?;
698				Ok(v)
699			}
700		}
701		let visitor = V::<Identifier>(PhantomData);
702		deserializer.deserialize_str(visitor)
703	}
704}
705
706impl<'de, Identifier: FromStr> Deserialize<'de> for IntExp<Identifier> {
707	fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<IntExp<Identifier>, D::Error> {
708		/// Visitor for `IntExp`
709		struct V<Ident>(PhantomData<Ident>);
710		impl<Ident: FromStr> Visitor<'_> for V<Ident> {
711			type Value = IntExp<Ident>;
712
713			fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
714				formatter.write_str("an integer expression")
715			}
716
717			fn visit_str<E: serde::de::Error>(self, v: &str) -> Result<Self::Value, E> {
718				let v = v.trim();
719				let (_, v) = Self::Value::parse(v)
720					.map_err(|_| E::custom(format!("invalid integer expression `{v}'")))?;
721				Ok(v)
722			}
723		}
724		deserializer.deserialize_str(V(PhantomData::<Identifier>))
725	}
726}
727
728impl<Identifier: Display> Display for IntExp<Identifier> {
729	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
730		match self {
731			IntExp::Const(i) => write!(f, "{}", i),
732			IntExp::Var(id) => write!(f, "{}", id),
733			IntExp::Neg(e) => write!(f, "neg({})", e),
734			IntExp::Abs(e) => write!(f, "abs({})", e),
735			IntExp::Add(es) => write!(
736				f,
737				"add({})",
738				es.iter()
739					.map(|e| e.to_string())
740					.collect::<Vec<_>>()
741					.join(",")
742			),
743			IntExp::Sub(e1, e2) => write!(f, "sub({},{})", e1, e2),
744			IntExp::Mul(es) => write!(
745				f,
746				"mul({})",
747				es.iter()
748					.map(|e| e.to_string())
749					.collect::<Vec<_>>()
750					.join(",")
751			),
752			IntExp::Div(e1, e2) => write!(f, "div({},{})", e1, e2),
753			IntExp::Mod(e1, e2) => write!(f, "mod({},{})", e1, e2),
754			IntExp::Sqr(e) => write!(f, "sqr({})", e),
755			IntExp::Pow(e1, e2) => write!(f, "pow({},{})", e1, e2),
756			IntExp::Min(es) => write!(
757				f,
758				"min({})",
759				es.iter()
760					.map(|e| e.to_string())
761					.collect::<Vec<_>>()
762					.join(",")
763			),
764			IntExp::Max(es) => write!(
765				f,
766				"max({})",
767				es.iter()
768					.map(|e| e.to_string())
769					.collect::<Vec<_>>()
770					.join(",")
771			),
772			IntExp::Dist(e1, e2) => write!(f, "dist({},{})", e1, e2),
773			IntExp::If(b, e1, e2) => write!(f, "if({},{},{})", b, e1, e2),
774			IntExp::Bool(b) => write!(f, "{}", b),
775			IntExp::Card(s) => write!(f, "card({})", s),
776		}
777	}
778}
779
780impl<Identifier: Display> Serialize for IntExp<Identifier> {
781	fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
782		serializer.serialize_str(&self.to_string())
783	}
784}
785
786impl<Identifier: FromStr> SetExp<Identifier> {
787	/// Parser combinator to parse a call set expression with 1 argument from a
788	/// string.
789	fn call_arg1(input: &str) -> IResult<&str, Self> {
790		let (input, tag) = tag("hull")(input)?;
791		let (input, _) = char('(')(input)?;
792		let (input, e) = Self::parse(input)?;
793		let (input, _) = char(')')(input)?;
794		Ok((
795			input,
796			match tag {
797				"hull" => SetExp::Hull,
798				_ => unreachable!(),
799			}(Box::new(e)),
800		))
801	}
802
803	/// Parser combinator to parse a call set expression with 2 arguments from a
804	/// string.
805	fn call_arg2(input: &str) -> IResult<&str, Self> {
806		let (input, tag) = tag("diff")(input)?;
807		let (input, _) = char('(')(input)?;
808		let (input, e1) = Self::parse(input)?;
809		let (input, _) = char(',')(input)?;
810		let (input, e2) = Self::parse(input)?;
811		let (input, _) = char(')')(input)?;
812		Ok((
813			input,
814			match tag {
815				"diff" => SetExp::Diff,
816				_ => unreachable!(),
817			}(Box::new(e1), Box::new(e2)),
818		))
819	}
820
821	/// Parser combinator to parse a call set expression with 3 arguments from a
822	/// string.
823	fn call_arg3(input: &str) -> IResult<&str, Self> {
824		let (input, tag) = alt((tag("union"), tag("inter"), tag("sdiff"))).parse(input)?;
825		let (input, _) = char('(')(input)?;
826		let (input, es) = separated_list1(char(','), Self::parse).parse(input)?;
827		let (input, _) = char(')')(input)?;
828		Ok((
829			input,
830			match tag {
831				"union" => SetExp::Union,
832				"inter" => SetExp::Inter,
833				"sdiff" => SetExp::SDiff,
834				_ => unreachable!(),
835			}(es),
836		))
837	}
838
839	/// Parser combinator to parse a set expression from a string.
840	pub(crate) fn parse(input: &str) -> IResult<&str, Self> {
841		alt((
842			map(
843				separated_pair(IntExp::parse, tag(".."), IntExp::parse),
844				|(from, to)| SetExp::Range((from, to)),
845			),
846			Self::call_arg1,
847			Self::call_arg2,
848			Self::call_arg3,
849			map(
850				delimited(
851					pair(tag("set"), char('(')),
852					separated_list0(char(','), IntExp::parse),
853					char(')'),
854				),
855				SetExp::Set,
856			),
857			map(VarRef::parse, SetExp::Var),
858		))
859		.parse(input)
860	}
861}
862
863impl<Identifier: Display> Display for SetExp<Identifier> {
864	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
865		match self {
866			SetExp::Var(id) => write!(f, "{}", id),
867			SetExp::Set(es) => write!(
868				f,
869				"{{{}}}",
870				es.iter()
871					.map(|e| e.to_string())
872					.collect::<Vec<_>>()
873					.join(",")
874			),
875			SetExp::Range((from, to)) => write!(f, "{}..{}", from, to),
876			SetExp::Hull(e) => write!(f, "hull({})", e),
877			SetExp::Diff(e1, e2) => write!(f, "diff({}, {})", e1, e2),
878			SetExp::Union(es) => write!(
879				f,
880				"union({})",
881				es.iter()
882					.map(|e| e.to_string())
883					.collect::<Vec<_>>()
884					.join(",")
885			),
886			SetExp::Inter(es) => write!(
887				f,
888				"inter({})",
889				es.iter()
890					.map(|e| e.to_string())
891					.collect::<Vec<_>>()
892					.join(",")
893			),
894			SetExp::SDiff(es) => write!(
895				f,
896				"sdiff({})",
897				es.iter()
898					.map(|e| e.to_string())
899					.collect::<Vec<_>>()
900					.join(",")
901			),
902		}
903	}
904}