1use crate::ast::{ExpressionIdGenerator, Span};
2use crate::error::LemmaError;
3use crate::parser::Rule;
4use crate::semantic::*;
5use pest::iterators::Pair;
6
7fn traceable_expr(
9 kind: ExpressionKind,
10 pair: &Pair<Rule>,
11 id_gen: &mut ExpressionIdGenerator,
12) -> Expression {
13 Expression::new(
14 kind,
15 Some(Span::from_pest_span(pair.as_span())),
16 id_gen.next_id(),
17 )
18}
19
20fn parse_literal_expression(
23 pair: Pair<Rule>,
24 id_gen: &mut ExpressionIdGenerator,
25) -> Result<Expression, LemmaError> {
26 let literal_pair = if pair.as_rule() == Rule::literal {
28 pair.into_inner()
29 .next()
30 .ok_or_else(|| LemmaError::Engine("Empty literal wrapper".to_string()))?
31 } else {
32 pair
33 };
34
35 let literal_value = crate::parser::literals::parse_literal(literal_pair.clone())?;
36 Ok(traceable_expr(
37 ExpressionKind::Literal(literal_value),
38 &literal_pair,
39 id_gen,
40 ))
41}
42
43fn parse_primary(
44 pair: Pair<Rule>,
45 id_gen: &mut ExpressionIdGenerator,
46) -> Result<Expression, LemmaError> {
47 for inner in pair.clone().into_inner() {
49 match inner.as_rule() {
50 Rule::literal
51 | Rule::number_literal
52 | Rule::string_literal
53 | Rule::boolean_literal
54 | Rule::regex_literal
55 | Rule::percentage_literal
56 | Rule::date_time_literal
57 | Rule::time_literal
58 | Rule::unit_literal => {
59 return parse_literal_expression(inner, id_gen);
60 }
61 Rule::reference_expression => {
62 return parse_reference_expression(inner, id_gen);
63 }
64 Rule::rule_reference => {
65 let rule_ref = parse_rule_reference(inner.clone())?;
66 return Ok(traceable_expr(
67 ExpressionKind::RuleReference(rule_ref),
68 &inner,
69 id_gen,
70 ));
71 }
72 Rule::fact_reference => {
73 let fact_ref = parse_fact_reference(inner.clone())?;
74 return Ok(traceable_expr(
75 ExpressionKind::FactReference(fact_ref),
76 &inner,
77 id_gen,
78 ));
79 }
80 Rule::expression_group => {
81 return parse_or_expression(inner, id_gen);
82 }
83 _ => {}
84 }
85 }
86 Err(LemmaError::Engine("Empty primary expression".to_string()))
87}
88
89pub(crate) fn parse_expression(
90 pair: Pair<Rule>,
91 id_gen: &mut ExpressionIdGenerator,
92) -> Result<Expression, LemmaError> {
93 if let Err(msg) = id_gen.push_depth() {
95 return Err(LemmaError::ResourceLimitExceeded {
96 limit_name: "max_expression_depth".to_string(),
97 limit_value: id_gen.max_depth().to_string(),
98 actual_value: msg
99 .split_whitespace()
100 .nth(2)
101 .unwrap_or("unknown")
102 .to_string(),
103 suggestion: "Simplify nested expressions to reduce depth".to_string(),
104 });
105 }
106
107 let result = parse_expression_impl(pair, id_gen);
108 id_gen.pop_depth();
109 result
110}
111
112fn parse_expression_impl(
113 pair: Pair<Rule>,
114 id_gen: &mut ExpressionIdGenerator,
115) -> Result<Expression, LemmaError> {
116 match pair.as_rule() {
118 Rule::comparable_base => return parse_comparable_base(pair, id_gen),
119 Rule::term => return parse_term(pair, id_gen),
120 Rule::power => return parse_power(pair, id_gen),
121 Rule::factor => return parse_factor(pair, id_gen),
122 Rule::primary => return parse_primary(pair, id_gen),
123 Rule::arithmetic_expression => return parse_arithmetic_expression(pair, id_gen),
124 Rule::comparison_expression => return parse_comparison_expression(pair, id_gen),
125 Rule::boolean_expression => return parse_logical_expression(pair, id_gen),
126 Rule::sqrt_expr
128 | Rule::sin_expr
129 | Rule::cos_expr
130 | Rule::tan_expr
131 | Rule::asin_expr
132 | Rule::acos_expr
133 | Rule::atan_expr
134 | Rule::log_expr
135 | Rule::exp_expr
136 | Rule::abs_expr
137 | Rule::floor_expr
138 | Rule::ceil_expr
139 | Rule::round_expr => return parse_logical_expression(pair, id_gen),
140 Rule::and_expression => return parse_and_expression(pair, id_gen),
141 Rule::or_expression => return parse_or_expression(pair, id_gen),
142 Rule::and_operand => return parse_and_operand(pair, id_gen),
143 Rule::expression_group => return parse_or_expression(pair, id_gen),
144 Rule::expression => {} _ => {}
146 }
147
148 for inner_pair in pair.clone().into_inner() {
149 match inner_pair.as_rule() {
150 Rule::literal
152 | Rule::number_literal
153 | Rule::string_literal
154 | Rule::boolean_literal
155 | Rule::regex_literal
156 | Rule::percentage_literal
157 | Rule::date_time_literal
158 | Rule::time_literal
159 | Rule::unit_literal => {
160 return parse_literal_expression(inner_pair, id_gen);
161 }
162
163 Rule::reference_expression => return parse_reference_expression(inner_pair, id_gen),
165
166 Rule::rule_reference => {
167 let rule_ref = parse_rule_reference(inner_pair.clone())?;
168 return Ok(traceable_expr(
169 ExpressionKind::RuleReference(rule_ref),
170 &inner_pair,
171 id_gen,
172 ));
173 }
174
175 Rule::fact_reference => {
176 let fact_ref = parse_fact_reference(inner_pair.clone())?;
177 return Ok(traceable_expr(
178 ExpressionKind::FactReference(fact_ref),
179 &inner_pair,
180 id_gen,
181 ));
182 }
183
184 Rule::primary
185 | Rule::arithmetic_expression
186 | Rule::comparison_expression
187 | Rule::boolean_expression
188 | Rule::and_expression
189 | Rule::or_expression
190 | Rule::and_operand
191 | Rule::expression_group => {
192 return parse_expression(inner_pair, id_gen);
193 }
194
195 Rule::not_expr
197 | Rule::have_expr
198 | Rule::have_not_expr
199 | Rule::not_have_expr
200 | Rule::sqrt_expr
201 | Rule::sin_expr
202 | Rule::cos_expr
203 | Rule::tan_expr
204 | Rule::asin_expr
205 | Rule::acos_expr
206 | Rule::atan_expr
207 | Rule::log_expr
208 | Rule::exp_expr
209 | Rule::abs_expr
210 | Rule::floor_expr
211 | Rule::ceil_expr
212 | Rule::round_expr => {
213 return parse_logical_expression(inner_pair, id_gen);
214 }
215
216 Rule::comparable_base | Rule::term | Rule::power | Rule::factor | Rule::expression => {
217 return parse_expression(inner_pair, id_gen);
218 }
219
220 _ => {}
221 }
222 }
223
224 Err(LemmaError::Engine(format!(
225 "Invalid expression: unable to parse '{}' as any valid expression type. Available rules: {:?}",
226 pair.as_str(),
227 pair.into_inner().map(|p| p.as_rule()).collect::<Vec<_>>()
228 )))
229}
230
231fn parse_reference_expression(
232 pair: Pair<Rule>,
233 id_gen: &mut ExpressionIdGenerator,
234) -> Result<Expression, LemmaError> {
235 if let Some(inner_pair) = pair.clone().into_inner().next() {
236 match inner_pair.as_rule() {
237 Rule::rule_reference => {
238 let rule_ref = parse_rule_reference(inner_pair)?;
239 let kind = ExpressionKind::RuleReference(rule_ref);
240 return Ok(traceable_expr(kind, &pair, id_gen));
241 }
242 Rule::fact_name => {
243 let kind = ExpressionKind::FactReference(FactReference {
244 reference: vec![inner_pair.as_str().to_string()],
245 });
246 return Ok(traceable_expr(kind, &pair, id_gen));
247 }
248 Rule::fact_reference => {
249 let fact_ref = parse_fact_reference(inner_pair)?;
250 let kind = ExpressionKind::FactReference(fact_ref);
251 return Ok(traceable_expr(kind, &pair, id_gen));
252 }
253 _ => {}
254 }
255 }
256 Err(LemmaError::Engine(
257 "Invalid reference expression".to_string(),
258 ))
259}
260
261fn parse_fact_reference(pair: Pair<Rule>) -> Result<FactReference, LemmaError> {
262 let mut reference = Vec::new();
263 for inner_pair in pair.into_inner() {
264 if inner_pair.as_rule() == Rule::label {
265 reference.push(inner_pair.as_str().to_string());
266 }
267 }
268 Ok(FactReference { reference })
269}
270
271fn parse_rule_reference(pair: Pair<Rule>) -> Result<RuleReference, LemmaError> {
272 let mut reference = Vec::new();
273 for inner_pair in pair.into_inner() {
274 if inner_pair.as_rule() == Rule::label {
275 reference.push(inner_pair.as_str().to_string());
276 }
277 }
278 Ok(RuleReference { reference })
279}
280
281fn parse_and_operand(
282 pair: Pair<Rule>,
283 id_gen: &mut ExpressionIdGenerator,
284) -> Result<Expression, LemmaError> {
285 let mut pairs = pair.into_inner();
287 let first = pairs
288 .next()
289 .ok_or_else(|| LemmaError::Engine("Empty and_operand".to_string()))?;
290
291 if first.as_rule() == Rule::boolean_expression {
293 return parse_logical_expression(first, id_gen);
294 }
295
296 let left = parse_expression(first, id_gen)?;
298
299 if let Some(op_pair) = pairs.next() {
301 if op_pair.as_rule() == Rule::comp_operator {
302 let inner_pair = op_pair
304 .clone()
305 .into_inner()
306 .next()
307 .ok_or_else(|| LemmaError::Engine("Empty comparison operator".to_string()))?;
308 let operator = match inner_pair.as_rule() {
309 Rule::comp_gt => ComparisonOperator::GreaterThan,
310 Rule::comp_lt => ComparisonOperator::LessThan,
311 Rule::comp_gte => ComparisonOperator::GreaterThanOrEqual,
312 Rule::comp_lte => ComparisonOperator::LessThanOrEqual,
313 Rule::comp_eq => ComparisonOperator::Equal,
314 Rule::comp_ne => ComparisonOperator::NotEqual,
315 Rule::comp_is => ComparisonOperator::Is,
316 Rule::comp_is_not => ComparisonOperator::IsNot,
317 _ => {
318 return Err(LemmaError::Engine(format!(
319 "Invalid comparison operator: {:?}",
320 inner_pair.as_rule()
321 )))
322 }
323 };
324 let right = parse_expression(
325 pairs.next().ok_or_else(|| {
326 LemmaError::Engine("Missing right operand in comparison".to_string())
327 })?,
328 id_gen,
329 )?;
330 let kind = ExpressionKind::Comparison(Box::new(left), operator, Box::new(right));
331 return Ok(traceable_expr(kind, &op_pair, id_gen));
332 }
333 }
334
335 Ok(left)
337}
338
339fn parse_and_expression(
340 pair: Pair<Rule>,
341 id_gen: &mut ExpressionIdGenerator,
342) -> Result<Expression, LemmaError> {
343 let mut pairs = pair.into_inner();
344 let mut left = parse_and_operand(
345 pairs.next().ok_or_else(|| {
346 LemmaError::Engine("Missing left operand in logical AND expression".to_string())
347 })?,
348 id_gen,
349 )?;
350
351 for right_pair in pairs {
354 if right_pair.as_rule() == Rule::and_operand {
355 let right = parse_and_operand(right_pair.clone(), id_gen)?;
356 let kind = ExpressionKind::LogicalAnd(Box::new(left), Box::new(right));
357 left = traceable_expr(kind, &right_pair, id_gen);
358 }
359 }
360
361 Ok(left)
362}
363
364pub(crate) fn parse_or_expression(
365 pair: Pair<Rule>,
366 id_gen: &mut ExpressionIdGenerator,
367) -> Result<Expression, LemmaError> {
368 let or_pair = if pair.as_rule() == Rule::expression_group {
370 pair.into_inner()
371 .next()
372 .ok_or_else(|| LemmaError::Engine("Empty expression_group".to_string()))?
373 } else {
374 pair
375 };
376
377 let mut pairs = or_pair.into_inner();
378 let mut left = parse_and_expression(
379 pairs.next().ok_or_else(|| {
380 LemmaError::Engine("Missing left operand in logical OR expression".to_string())
381 })?,
382 id_gen,
383 )?;
384
385 for right_pair in pairs {
388 if right_pair.as_rule() == Rule::and_expression {
389 let right = parse_and_expression(right_pair.clone(), id_gen)?;
390 let kind = ExpressionKind::LogicalOr(Box::new(left), Box::new(right));
391 left = traceable_expr(kind, &right_pair, id_gen);
392 }
393 }
394
395 Ok(left)
396}
397
398fn parse_arithmetic_expression(
399 pair: Pair<Rule>,
400 id_gen: &mut ExpressionIdGenerator,
401) -> Result<Expression, LemmaError> {
402 let mut pairs = pair.clone().into_inner();
403 let mut left = parse_term(
404 pairs.next().ok_or_else(|| {
405 LemmaError::Engine("Missing left term in arithmetic expression".to_string())
406 })?,
407 id_gen,
408 )?;
409
410 while let Some(op_pair) = pairs.next() {
411 let operation = match op_pair.as_rule() {
412 Rule::add_plus => ArithmeticOperation::Add,
413 Rule::add_minus => ArithmeticOperation::Subtract,
414 _ => {
415 return Err(LemmaError::Engine(format!(
416 "Unexpected operator in arithmetic expression: {:?}",
417 op_pair.as_rule()
418 )))
419 }
420 };
421
422 let right = parse_term(
423 pairs.next().ok_or_else(|| {
424 LemmaError::Engine("Missing right term in arithmetic expression".to_string())
425 })?,
426 id_gen,
427 )?;
428
429 let kind = ExpressionKind::Arithmetic(Box::new(left), operation, Box::new(right));
430 left = traceable_expr(kind, &pair, id_gen);
431 }
432
433 Ok(left)
434}
435
436fn parse_term(
437 pair: Pair<Rule>,
438 id_gen: &mut ExpressionIdGenerator,
439) -> Result<Expression, LemmaError> {
440 let mut pairs = pair.clone().into_inner();
441 let mut left = parse_power(
442 pairs
443 .next()
444 .ok_or_else(|| LemmaError::Engine("Missing left power in term".to_string()))?,
445 id_gen,
446 )?;
447
448 while let Some(op_pair) = pairs.next() {
449 let operation = match op_pair.as_rule() {
450 Rule::mul_star => ArithmeticOperation::Multiply,
451 Rule::mul_slash => ArithmeticOperation::Divide,
452 Rule::mul_percent => ArithmeticOperation::Modulo,
453 _ => {
454 return Err(LemmaError::Engine(format!(
455 "Unexpected operator in term: {:?}",
456 op_pair.as_rule()
457 )))
458 }
459 };
460
461 let right = parse_power(
462 pairs
463 .next()
464 .ok_or_else(|| LemmaError::Engine("Missing right power in term".to_string()))?,
465 id_gen,
466 )?;
467
468 let kind = ExpressionKind::Arithmetic(Box::new(left), operation, Box::new(right));
469 left = traceable_expr(kind, &pair, id_gen);
470 }
471
472 Ok(left)
473}
474
475fn parse_power(
476 pair: Pair<Rule>,
477 id_gen: &mut ExpressionIdGenerator,
478) -> Result<Expression, LemmaError> {
479 let mut pairs = pair.clone().into_inner();
480 let left = parse_factor(
481 pairs
482 .next()
483 .ok_or_else(|| LemmaError::Engine("Missing factor in power".to_string()))?,
484 id_gen,
485 )?;
486
487 if let Some(op_pair) = pairs.next() {
488 if op_pair.as_rule() == Rule::pow_caret {
489 let right = parse_power(
490 pairs.next().ok_or_else(|| {
491 LemmaError::Engine("Missing right power in power expression".to_string())
492 })?,
493 id_gen,
494 )?;
495
496 let kind = ExpressionKind::Arithmetic(
497 Box::new(left),
498 ArithmeticOperation::Power,
499 Box::new(right),
500 );
501 return Ok(traceable_expr(kind, &pair, id_gen));
502 }
503 }
504
505 Ok(left)
506}
507
508fn parse_factor(
509 pair: Pair<Rule>,
510 id_gen: &mut ExpressionIdGenerator,
511) -> Result<Expression, LemmaError> {
512 let mut pairs = pair.clone().into_inner();
513 let mut is_negative = false;
514
515 if let Some(first_pair) = pairs.next() {
517 match first_pair.as_rule() {
518 Rule::unary_minus => {
519 is_negative = true;
520 }
521 Rule::unary_plus => {
522 }
524 _ => {
525 let expr = parse_expression(first_pair, id_gen)?;
526 return Ok(expr);
527 }
528 }
529 }
530
531 let expr = if let Some(expr_pair) = pairs.next() {
533 parse_expression(expr_pair, id_gen)?
534 } else {
535 return Err(LemmaError::Engine(
536 "Missing expression after unary operator".to_string(),
537 ));
538 };
539
540 if is_negative {
542 let zero = traceable_expr(
543 ExpressionKind::Literal(LiteralValue::Number(rust_decimal::Decimal::ZERO)),
544 &pair,
545 id_gen,
546 );
547 let kind = ExpressionKind::Arithmetic(
548 Box::new(zero),
549 ArithmeticOperation::Subtract,
550 Box::new(expr),
551 );
552 Ok(traceable_expr(kind, &pair, id_gen))
553 } else {
554 Ok(expr)
555 }
556}
557
558fn parse_comparison_expression(
559 pair: Pair<Rule>,
560 id_gen: &mut ExpressionIdGenerator,
561) -> Result<Expression, LemmaError> {
562 let mut pairs = pair.clone().into_inner();
563 let left = parse_expression(
564 pairs.next().ok_or_else(|| {
565 LemmaError::Engine("Missing left operand in comparison expression".to_string())
566 })?,
567 id_gen,
568 )?;
569
570 if let Some(op_pair) = pairs.next() {
571 let operator = match op_pair.as_rule() {
572 Rule::comp_operator => {
573 let inner_pair = op_pair
575 .into_inner()
576 .next()
577 .ok_or_else(|| LemmaError::Engine("Empty comparison operator".to_string()))?;
578 match inner_pair.as_rule() {
579 Rule::comp_gt => ComparisonOperator::GreaterThan,
580 Rule::comp_lt => ComparisonOperator::LessThan,
581 Rule::comp_gte => ComparisonOperator::GreaterThanOrEqual,
582 Rule::comp_lte => ComparisonOperator::LessThanOrEqual,
583 Rule::comp_eq => ComparisonOperator::Equal,
584 Rule::comp_ne => ComparisonOperator::NotEqual,
585 Rule::comp_is => ComparisonOperator::Is,
586 Rule::comp_is_not => ComparisonOperator::IsNot,
587 _ => {
588 return Err(LemmaError::Engine(format!(
589 "Invalid comparison operator: {:?}",
590 inner_pair.as_rule()
591 )))
592 }
593 }
594 }
595 Rule::comp_gt => ComparisonOperator::GreaterThan,
596 Rule::comp_lt => ComparisonOperator::LessThan,
597 Rule::comp_gte => ComparisonOperator::GreaterThanOrEqual,
598 Rule::comp_lte => ComparisonOperator::LessThanOrEqual,
599 Rule::comp_eq => ComparisonOperator::Equal,
600 Rule::comp_ne => ComparisonOperator::NotEqual,
601 Rule::comp_is => ComparisonOperator::Is,
602 Rule::comp_is_not => ComparisonOperator::IsNot,
603 _ => {
604 return Err(LemmaError::Engine(format!(
605 "Invalid comparison operator: {:?}",
606 op_pair.as_rule()
607 )))
608 }
609 };
610
611 let right = parse_expression(
612 pairs.next().ok_or_else(|| {
613 LemmaError::Engine("Missing right operand in comparison expression".to_string())
614 })?,
615 id_gen,
616 )?;
617
618 let kind = ExpressionKind::Comparison(Box::new(left), operator, Box::new(right));
619 return Ok(traceable_expr(kind, &pair, id_gen));
620 }
621
622 Ok(left)
623}
624
625fn parse_logical_expression(
626 pair: Pair<Rule>,
627 id_gen: &mut ExpressionIdGenerator,
628) -> Result<Expression, LemmaError> {
629 match pair.as_rule() {
631 Rule::sqrt_expr
632 | Rule::sin_expr
633 | Rule::cos_expr
634 | Rule::tan_expr
635 | Rule::asin_expr
636 | Rule::acos_expr
637 | Rule::atan_expr
638 | Rule::log_expr
639 | Rule::exp_expr
640 | Rule::abs_expr
641 | Rule::floor_expr
642 | Rule::ceil_expr
643 | Rule::round_expr => {
644 let operator = match pair.as_rule() {
645 Rule::sqrt_expr => MathematicalOperator::Sqrt,
646 Rule::sin_expr => MathematicalOperator::Sin,
647 Rule::cos_expr => MathematicalOperator::Cos,
648 Rule::tan_expr => MathematicalOperator::Tan,
649 Rule::asin_expr => MathematicalOperator::Asin,
650 Rule::acos_expr => MathematicalOperator::Acos,
651 Rule::atan_expr => MathematicalOperator::Atan,
652 Rule::log_expr => MathematicalOperator::Log,
653 Rule::exp_expr => MathematicalOperator::Exp,
654 Rule::abs_expr => MathematicalOperator::Abs,
655 Rule::floor_expr => MathematicalOperator::Floor,
656 Rule::ceil_expr => MathematicalOperator::Ceil,
657 Rule::round_expr => MathematicalOperator::Round,
658 _ => unreachable!(),
659 };
660
661 for inner in pair.clone().into_inner() {
662 if inner.as_rule() == Rule::arithmetic_expression
663 || inner.as_rule() == Rule::primary
664 {
665 let operand = parse_expression(inner, id_gen)?;
666 let kind = ExpressionKind::MathematicalOperator(operator, Box::new(operand));
667 return Ok(traceable_expr(kind, &pair, id_gen));
668 }
669 }
670 return Err(LemmaError::Engine(
671 "Mathematical operator missing operand".to_string(),
672 ));
673 }
674 _ => {}
675 }
676 if let Some(node) = pair.into_inner().next() {
677 match node.as_rule() {
678 Rule::reference_expression => return parse_reference_expression(node, id_gen),
679 Rule::literal => return parse_expression(node, id_gen),
680 Rule::primary => return parse_primary(node, id_gen),
681 Rule::have_expr => {
682 for inner in node.clone().into_inner() {
683 if inner.as_rule() == Rule::reference_expression {
684 let ref_expr = parse_reference_expression(inner.clone(), id_gen)?;
685 if let ExpressionKind::FactReference(f) = &ref_expr.kind {
686 let kind = ExpressionKind::FactHasAnyValue(f.clone());
687 return Ok(traceable_expr(kind, &node, id_gen));
688 }
689 return Ok(ref_expr);
690 }
691 }
692 return Err(LemmaError::Engine("have: missing reference".to_string()));
693 }
694 Rule::have_not_expr | Rule::not_have_expr | Rule::not_expr => {
695 let rule_type = node.as_rule();
696 for inner in node.clone().into_inner() {
697 if inner.as_rule() == Rule::reference_expression {
698 let negated_expr = parse_reference_expression(inner, id_gen)?;
699 let negation_type = match rule_type {
700 Rule::not_expr => NegationType::Not,
701 Rule::have_not_expr => NegationType::HaveNot,
702 Rule::not_have_expr => NegationType::NotHave,
703 _ => NegationType::Not,
704 };
705 let kind =
706 ExpressionKind::LogicalNegation(Box::new(negated_expr), negation_type);
707 return Ok(traceable_expr(kind, &node, id_gen));
708 } else if inner.as_rule() == Rule::primary {
709 let negated_expr = parse_primary(inner, id_gen)?;
710 let negation_type = match rule_type {
711 Rule::not_expr => NegationType::Not,
712 Rule::have_not_expr => NegationType::HaveNot,
713 Rule::not_have_expr => NegationType::NotHave,
714 _ => NegationType::Not,
715 };
716 let kind =
717 ExpressionKind::LogicalNegation(Box::new(negated_expr), negation_type);
718 return Ok(traceable_expr(kind, &node, id_gen));
719 } else if inner.as_rule() == Rule::literal {
720 let negated_expr = parse_expression(inner, id_gen)?;
721 let negation_type = match rule_type {
722 Rule::not_expr => NegationType::Not,
723 Rule::have_not_expr => NegationType::HaveNot,
724 Rule::not_have_expr => NegationType::NotHave,
725 _ => NegationType::Not,
726 };
727 let kind =
728 ExpressionKind::LogicalNegation(Box::new(negated_expr), negation_type);
729 return Ok(traceable_expr(kind, &node, id_gen));
730 }
731 }
732 return Err(LemmaError::Engine(
733 "not/have not: missing reference".to_string(),
734 ));
735 }
736 Rule::sqrt_expr
737 | Rule::sin_expr
738 | Rule::cos_expr
739 | Rule::tan_expr
740 | Rule::asin_expr
741 | Rule::acos_expr
742 | Rule::atan_expr
743 | Rule::log_expr
744 | Rule::exp_expr
745 | Rule::abs_expr
746 | Rule::floor_expr
747 | Rule::ceil_expr
748 | Rule::round_expr => {
749 let operator = match node.as_rule() {
750 Rule::sqrt_expr => MathematicalOperator::Sqrt,
751 Rule::sin_expr => MathematicalOperator::Sin,
752 Rule::cos_expr => MathematicalOperator::Cos,
753 Rule::tan_expr => MathematicalOperator::Tan,
754 Rule::asin_expr => MathematicalOperator::Asin,
755 Rule::acos_expr => MathematicalOperator::Acos,
756 Rule::atan_expr => MathematicalOperator::Atan,
757 Rule::log_expr => MathematicalOperator::Log,
758 Rule::exp_expr => MathematicalOperator::Exp,
759 Rule::abs_expr => MathematicalOperator::Abs,
760 Rule::floor_expr => MathematicalOperator::Floor,
761 Rule::ceil_expr => MathematicalOperator::Ceil,
762 Rule::round_expr => MathematicalOperator::Round,
763 _ => {
764 return Err(LemmaError::Engine(
765 "Unknown mathematical operator".to_string(),
766 ))
767 }
768 };
769
770 for inner in node.clone().into_inner() {
771 if inner.as_rule() == Rule::arithmetic_expression
772 || inner.as_rule() == Rule::primary
773 {
774 let operand = parse_expression(inner, id_gen)?;
775 let kind =
776 ExpressionKind::MathematicalOperator(operator, Box::new(operand));
777 return Ok(traceable_expr(kind, &node, id_gen));
778 }
779 }
780 return Err(LemmaError::Engine(
781 "Mathematical operator missing operand".to_string(),
782 ));
783 }
784 _ => {}
785 }
786 }
787 Err(LemmaError::Engine("Empty logical expression".to_string()))
788}
789
790fn parse_comparable_base(
791 pair: Pair<Rule>,
792 id_gen: &mut ExpressionIdGenerator,
793) -> Result<Expression, LemmaError> {
794 let mut pairs = pair.clone().into_inner();
796
797 let arith_expr = parse_expression(
798 pairs.next().ok_or_else(|| {
799 LemmaError::Engine("No arithmetic expression in comparable_base".to_string())
800 })?,
801 id_gen,
802 )?;
803
804 if let Some(unit_pair) = pairs.next() {
806 if unit_pair.as_rule() == Rule::unit_word {
807 let target_unit = super::units::resolve_conversion_target(unit_pair.as_str())?;
808 let kind = ExpressionKind::UnitConversion(Box::new(arith_expr), target_unit);
809 return Ok(traceable_expr(kind, &pair, id_gen));
810 }
811 }
812
813 Ok(arith_expr)
815}