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 match pair.as_rule() {
95 Rule::comparable_base => return parse_comparable_base(pair, id_gen),
96 Rule::term => return parse_term(pair, id_gen),
97 Rule::power => return parse_power(pair, id_gen),
98 Rule::factor => return parse_factor(pair, id_gen),
99 Rule::primary => return parse_primary(pair, id_gen),
100 Rule::arithmetic_expression => return parse_arithmetic_expression(pair, id_gen),
101 Rule::comparison_expression => return parse_comparison_expression(pair, id_gen),
102 Rule::boolean_expression => return parse_logical_expression(pair, id_gen),
103 Rule::and_expression => return parse_and_expression(pair, id_gen),
104 Rule::or_expression => return parse_or_expression(pair, id_gen),
105 Rule::and_operand => return parse_and_operand(pair, id_gen),
106 Rule::expression_group => return parse_or_expression(pair, id_gen),
107 Rule::expression => {} _ => {}
109 }
110
111 for inner_pair in pair.clone().into_inner() {
112 match inner_pair.as_rule() {
113 Rule::literal
115 | Rule::number_literal
116 | Rule::string_literal
117 | Rule::boolean_literal
118 | Rule::regex_literal
119 | Rule::percentage_literal
120 | Rule::date_time_literal
121 | Rule::time_literal
122 | Rule::unit_literal => {
123 return parse_literal_expression(inner_pair, id_gen);
124 }
125
126 Rule::reference_expression => return parse_reference_expression(inner_pair, id_gen),
128
129 Rule::rule_reference => {
130 let rule_ref = parse_rule_reference(inner_pair.clone())?;
131 return Ok(traceable_expr(
132 ExpressionKind::RuleReference(rule_ref),
133 &inner_pair,
134 id_gen,
135 ));
136 }
137
138 Rule::fact_reference => {
139 let fact_ref = parse_fact_reference(inner_pair.clone())?;
140 return Ok(traceable_expr(
141 ExpressionKind::FactReference(fact_ref),
142 &inner_pair,
143 id_gen,
144 ));
145 }
146
147 Rule::primary
148 | Rule::arithmetic_expression
149 | Rule::comparison_expression
150 | Rule::boolean_expression
151 | Rule::and_expression
152 | Rule::or_expression
153 | Rule::and_operand
154 | Rule::expression_group => {
155 return parse_expression(inner_pair, id_gen);
156 }
157
158 Rule::not_expr
160 | Rule::have_expr
161 | Rule::have_not_expr
162 | Rule::not_have_expr
163 | Rule::sqrt_expr
164 | Rule::sin_expr
165 | Rule::cos_expr
166 | Rule::tan_expr
167 | Rule::asin_expr
168 | Rule::acos_expr
169 | Rule::atan_expr
170 | Rule::log_expr
171 | Rule::exp_expr => {
172 return parse_logical_expression(inner_pair, id_gen);
173 }
174
175 Rule::comparable_base | Rule::term | Rule::power | Rule::factor | Rule::expression => {
176 return parse_expression(inner_pair, id_gen);
177 }
178
179 _ => {}
180 }
181 }
182
183 Err(LemmaError::Engine(format!(
184 "Invalid expression: unable to parse '{}' as any valid expression type. Available rules: {:?}",
185 pair.as_str(),
186 pair.into_inner().map(|p| p.as_rule()).collect::<Vec<_>>()
187 )))
188}
189
190fn parse_reference_expression(
191 pair: Pair<Rule>,
192 id_gen: &mut ExpressionIdGenerator,
193) -> Result<Expression, LemmaError> {
194 if let Some(inner_pair) = pair.clone().into_inner().next() {
195 match inner_pair.as_rule() {
196 Rule::rule_reference => {
197 let rule_ref = parse_rule_reference(inner_pair)?;
198 let kind = ExpressionKind::RuleReference(rule_ref);
199 return Ok(traceable_expr(kind, &pair, id_gen));
200 }
201 Rule::fact_name => {
202 let kind = ExpressionKind::FactReference(FactReference {
203 reference: vec![inner_pair.as_str().to_string()],
204 });
205 return Ok(traceable_expr(kind, &pair, id_gen));
206 }
207 Rule::fact_reference => {
208 let fact_ref = parse_fact_reference(inner_pair)?;
209 let kind = ExpressionKind::FactReference(fact_ref);
210 return Ok(traceable_expr(kind, &pair, id_gen));
211 }
212 _ => {}
213 }
214 }
215 Err(LemmaError::Engine(
216 "Invalid reference expression".to_string(),
217 ))
218}
219
220fn parse_fact_reference(pair: Pair<Rule>) -> Result<FactReference, LemmaError> {
221 let mut reference = Vec::new();
222 for inner_pair in pair.into_inner() {
223 if inner_pair.as_rule() == Rule::label {
224 reference.push(inner_pair.as_str().to_string());
225 }
226 }
227 Ok(FactReference { reference })
228}
229
230fn parse_rule_reference(pair: Pair<Rule>) -> Result<RuleReference, LemmaError> {
231 let mut reference = Vec::new();
232 for inner_pair in pair.into_inner() {
233 if inner_pair.as_rule() == Rule::label {
234 reference.push(inner_pair.as_str().to_string());
235 }
236 }
237 Ok(RuleReference { reference })
238}
239
240fn parse_and_operand(
241 pair: Pair<Rule>,
242 id_gen: &mut ExpressionIdGenerator,
243) -> Result<Expression, LemmaError> {
244 let mut pairs = pair.into_inner();
246 let first = pairs
247 .next()
248 .ok_or_else(|| LemmaError::Engine("Empty and_operand".to_string()))?;
249
250 if first.as_rule() == Rule::boolean_expression {
252 return parse_logical_expression(first, id_gen);
253 }
254
255 let left = parse_expression(first, id_gen)?;
257
258 if let Some(op_pair) = pairs.next() {
260 if op_pair.as_rule() == Rule::comp_operator {
261 let inner_pair = op_pair
263 .clone()
264 .into_inner()
265 .next()
266 .ok_or_else(|| LemmaError::Engine("Empty comparison operator".to_string()))?;
267 let operator = match inner_pair.as_rule() {
268 Rule::comp_gt => ComparisonOperator::GreaterThan,
269 Rule::comp_lt => ComparisonOperator::LessThan,
270 Rule::comp_gte => ComparisonOperator::GreaterThanOrEqual,
271 Rule::comp_lte => ComparisonOperator::LessThanOrEqual,
272 Rule::comp_eq => ComparisonOperator::Equal,
273 Rule::comp_ne => ComparisonOperator::NotEqual,
274 Rule::comp_is => ComparisonOperator::Is,
275 Rule::comp_is_not => ComparisonOperator::IsNot,
276 _ => {
277 return Err(LemmaError::Engine(format!(
278 "Invalid comparison operator: {:?}",
279 inner_pair.as_rule()
280 )))
281 }
282 };
283 let right = parse_expression(
284 pairs.next().ok_or_else(|| {
285 LemmaError::Engine("Missing right operand in comparison".to_string())
286 })?,
287 id_gen,
288 )?;
289 let kind = ExpressionKind::Comparison(Box::new(left), operator, Box::new(right));
290 return Ok(traceable_expr(kind, &op_pair, id_gen));
291 }
292 }
293
294 Ok(left)
296}
297
298fn parse_and_expression(
299 pair: Pair<Rule>,
300 id_gen: &mut ExpressionIdGenerator,
301) -> Result<Expression, LemmaError> {
302 let mut pairs = pair.into_inner();
303 let mut left = parse_and_operand(
304 pairs.next().ok_or_else(|| {
305 LemmaError::Engine("Missing left operand in logical AND expression".to_string())
306 })?,
307 id_gen,
308 )?;
309
310 for right_pair in pairs {
313 if right_pair.as_rule() == Rule::and_operand {
314 let right = parse_and_operand(right_pair.clone(), id_gen)?;
315 let kind = ExpressionKind::LogicalAnd(Box::new(left), Box::new(right));
316 left = traceable_expr(kind, &right_pair, id_gen);
317 }
318 }
319
320 Ok(left)
321}
322
323pub(crate) fn parse_or_expression(
324 pair: Pair<Rule>,
325 id_gen: &mut ExpressionIdGenerator,
326) -> Result<Expression, LemmaError> {
327 let or_pair = if pair.as_rule() == Rule::expression_group {
329 pair.into_inner()
330 .next()
331 .ok_or_else(|| LemmaError::Engine("Empty expression_group".to_string()))?
332 } else {
333 pair
334 };
335
336 let mut pairs = or_pair.into_inner();
337 let mut left = parse_and_expression(
338 pairs.next().ok_or_else(|| {
339 LemmaError::Engine("Missing left operand in logical OR expression".to_string())
340 })?,
341 id_gen,
342 )?;
343
344 for right_pair in pairs {
347 if right_pair.as_rule() == Rule::and_expression {
348 let right = parse_and_expression(right_pair.clone(), id_gen)?;
349 let kind = ExpressionKind::LogicalOr(Box::new(left), Box::new(right));
350 left = traceable_expr(kind, &right_pair, id_gen);
351 }
352 }
353
354 Ok(left)
355}
356
357fn parse_arithmetic_expression(
358 pair: Pair<Rule>,
359 id_gen: &mut ExpressionIdGenerator,
360) -> Result<Expression, LemmaError> {
361 let mut pairs = pair.clone().into_inner();
362 let mut left = parse_term(
363 pairs.next().ok_or_else(|| {
364 LemmaError::Engine("Missing left term in arithmetic expression".to_string())
365 })?,
366 id_gen,
367 )?;
368
369 while let Some(op_pair) = pairs.next() {
370 let operation = match op_pair.as_rule() {
371 Rule::add_plus => ArithmeticOperation::Add,
372 Rule::add_minus => ArithmeticOperation::Subtract,
373 _ => {
374 return Err(LemmaError::Engine(format!(
375 "Unexpected operator in arithmetic expression: {:?}",
376 op_pair.as_rule()
377 )))
378 }
379 };
380
381 let right = parse_term(
382 pairs.next().ok_or_else(|| {
383 LemmaError::Engine("Missing right term in arithmetic expression".to_string())
384 })?,
385 id_gen,
386 )?;
387
388 let kind = ExpressionKind::Arithmetic(Box::new(left), operation, Box::new(right));
389 left = traceable_expr(kind, &pair, id_gen);
390 }
391
392 Ok(left)
393}
394
395fn parse_term(
396 pair: Pair<Rule>,
397 id_gen: &mut ExpressionIdGenerator,
398) -> Result<Expression, LemmaError> {
399 let mut pairs = pair.clone().into_inner();
400 let mut left = parse_power(
401 pairs
402 .next()
403 .ok_or_else(|| LemmaError::Engine("Missing left power in term".to_string()))?,
404 id_gen,
405 )?;
406
407 while let Some(op_pair) = pairs.next() {
408 let operation = match op_pair.as_rule() {
409 Rule::mul_star => ArithmeticOperation::Multiply,
410 Rule::mul_slash => ArithmeticOperation::Divide,
411 Rule::mul_percent => ArithmeticOperation::Modulo,
412 _ => {
413 return Err(LemmaError::Engine(format!(
414 "Unexpected operator in term: {:?}",
415 op_pair.as_rule()
416 )))
417 }
418 };
419
420 let right = parse_power(
421 pairs
422 .next()
423 .ok_or_else(|| LemmaError::Engine("Missing right power in term".to_string()))?,
424 id_gen,
425 )?;
426
427 let kind = ExpressionKind::Arithmetic(Box::new(left), operation, Box::new(right));
428 left = traceable_expr(kind, &pair, id_gen);
429 }
430
431 Ok(left)
432}
433
434fn parse_power(
435 pair: Pair<Rule>,
436 id_gen: &mut ExpressionIdGenerator,
437) -> Result<Expression, LemmaError> {
438 let mut pairs = pair.clone().into_inner();
439 let left = parse_factor(
440 pairs
441 .next()
442 .ok_or_else(|| LemmaError::Engine("Missing factor in power".to_string()))?,
443 id_gen,
444 )?;
445
446 if let Some(op_pair) = pairs.next() {
447 if op_pair.as_rule() == Rule::pow_caret {
448 let right = parse_power(
449 pairs.next().ok_or_else(|| {
450 LemmaError::Engine("Missing right power in power expression".to_string())
451 })?,
452 id_gen,
453 )?;
454
455 let kind = ExpressionKind::Arithmetic(
456 Box::new(left),
457 ArithmeticOperation::Power,
458 Box::new(right),
459 );
460 return Ok(traceable_expr(kind, &pair, id_gen));
461 }
462 }
463
464 Ok(left)
465}
466
467fn parse_factor(
468 pair: Pair<Rule>,
469 id_gen: &mut ExpressionIdGenerator,
470) -> Result<Expression, LemmaError> {
471 let mut pairs = pair.clone().into_inner();
472 let mut is_negative = false;
473
474 if let Some(first_pair) = pairs.next() {
476 match first_pair.as_rule() {
477 Rule::unary_minus => {
478 is_negative = true;
479 }
480 Rule::unary_plus => {
481 }
483 _ => {
484 let expr = parse_expression(first_pair, id_gen)?;
485 return Ok(expr);
486 }
487 }
488 }
489
490 let expr = if let Some(expr_pair) = pairs.next() {
492 parse_expression(expr_pair, id_gen)?
493 } else {
494 return Err(LemmaError::Engine(
495 "Missing expression after unary operator".to_string(),
496 ));
497 };
498
499 if is_negative {
501 let zero = traceable_expr(
502 ExpressionKind::Literal(LiteralValue::Number(rust_decimal::Decimal::ZERO)),
503 &pair,
504 id_gen,
505 );
506 let kind = ExpressionKind::Arithmetic(
507 Box::new(zero),
508 ArithmeticOperation::Subtract,
509 Box::new(expr),
510 );
511 Ok(traceable_expr(kind, &pair, id_gen))
512 } else {
513 Ok(expr)
514 }
515}
516
517fn parse_comparison_expression(
518 pair: Pair<Rule>,
519 id_gen: &mut ExpressionIdGenerator,
520) -> Result<Expression, LemmaError> {
521 let mut pairs = pair.clone().into_inner();
522 let left = parse_expression(
523 pairs.next().ok_or_else(|| {
524 LemmaError::Engine("Missing left operand in comparison expression".to_string())
525 })?,
526 id_gen,
527 )?;
528
529 if let Some(op_pair) = pairs.next() {
530 let operator = match op_pair.as_rule() {
531 Rule::comp_operator => {
532 let inner_pair = op_pair
534 .into_inner()
535 .next()
536 .ok_or_else(|| LemmaError::Engine("Empty comparison operator".to_string()))?;
537 match inner_pair.as_rule() {
538 Rule::comp_gt => ComparisonOperator::GreaterThan,
539 Rule::comp_lt => ComparisonOperator::LessThan,
540 Rule::comp_gte => ComparisonOperator::GreaterThanOrEqual,
541 Rule::comp_lte => ComparisonOperator::LessThanOrEqual,
542 Rule::comp_eq => ComparisonOperator::Equal,
543 Rule::comp_ne => ComparisonOperator::NotEqual,
544 Rule::comp_is => ComparisonOperator::Is,
545 Rule::comp_is_not => ComparisonOperator::IsNot,
546 _ => {
547 return Err(LemmaError::Engine(format!(
548 "Invalid comparison operator: {:?}",
549 inner_pair.as_rule()
550 )))
551 }
552 }
553 }
554 Rule::comp_gt => ComparisonOperator::GreaterThan,
555 Rule::comp_lt => ComparisonOperator::LessThan,
556 Rule::comp_gte => ComparisonOperator::GreaterThanOrEqual,
557 Rule::comp_lte => ComparisonOperator::LessThanOrEqual,
558 Rule::comp_eq => ComparisonOperator::Equal,
559 Rule::comp_ne => ComparisonOperator::NotEqual,
560 Rule::comp_is => ComparisonOperator::Is,
561 Rule::comp_is_not => ComparisonOperator::IsNot,
562 _ => {
563 return Err(LemmaError::Engine(format!(
564 "Invalid comparison operator: {:?}",
565 op_pair.as_rule()
566 )))
567 }
568 };
569
570 let right = parse_expression(
571 pairs.next().ok_or_else(|| {
572 LemmaError::Engine("Missing right operand in comparison expression".to_string())
573 })?,
574 id_gen,
575 )?;
576
577 let kind = ExpressionKind::Comparison(Box::new(left), operator, Box::new(right));
578 return Ok(traceable_expr(kind, &pair, id_gen));
579 }
580
581 Ok(left)
582}
583
584fn parse_logical_expression(
585 pair: Pair<Rule>,
586 id_gen: &mut ExpressionIdGenerator,
587) -> Result<Expression, LemmaError> {
588 if let Some(node) = pair.into_inner().next() {
589 match node.as_rule() {
590 Rule::reference_expression => return parse_reference_expression(node, id_gen),
591 Rule::literal => return parse_expression(node, id_gen),
592 Rule::primary => return parse_primary(node, id_gen),
593 Rule::have_expr => {
594 for inner in node.clone().into_inner() {
595 if inner.as_rule() == Rule::reference_expression {
596 let ref_expr = parse_reference_expression(inner.clone(), id_gen)?;
597 if let ExpressionKind::FactReference(f) = &ref_expr.kind {
598 let kind = ExpressionKind::FactHasAnyValue(f.clone());
599 return Ok(traceable_expr(kind, &node, id_gen));
600 }
601 return Ok(ref_expr);
602 }
603 }
604 return Err(LemmaError::Engine("have: missing reference".to_string()));
605 }
606 Rule::have_not_expr | Rule::not_have_expr | Rule::not_expr => {
607 let rule_type = node.as_rule();
608 for inner in node.clone().into_inner() {
609 if inner.as_rule() == Rule::reference_expression {
610 let negated_expr = parse_reference_expression(inner, id_gen)?;
611 let negation_type = match rule_type {
612 Rule::not_expr => NegationType::Not,
613 Rule::have_not_expr => NegationType::HaveNot,
614 Rule::not_have_expr => NegationType::NotHave,
615 _ => NegationType::Not,
616 };
617 let kind =
618 ExpressionKind::LogicalNegation(Box::new(negated_expr), negation_type);
619 return Ok(traceable_expr(kind, &node, id_gen));
620 } else if inner.as_rule() == Rule::primary {
621 let negated_expr = parse_primary(inner, id_gen)?;
622 let negation_type = match rule_type {
623 Rule::not_expr => NegationType::Not,
624 Rule::have_not_expr => NegationType::HaveNot,
625 Rule::not_have_expr => NegationType::NotHave,
626 _ => NegationType::Not,
627 };
628 let kind =
629 ExpressionKind::LogicalNegation(Box::new(negated_expr), negation_type);
630 return Ok(traceable_expr(kind, &node, id_gen));
631 } else if inner.as_rule() == Rule::literal {
632 let negated_expr = parse_expression(inner, id_gen)?;
633 let negation_type = match rule_type {
634 Rule::not_expr => NegationType::Not,
635 Rule::have_not_expr => NegationType::HaveNot,
636 Rule::not_have_expr => NegationType::NotHave,
637 _ => NegationType::Not,
638 };
639 let kind =
640 ExpressionKind::LogicalNegation(Box::new(negated_expr), negation_type);
641 return Ok(traceable_expr(kind, &node, id_gen));
642 }
643 }
644 return Err(LemmaError::Engine(
645 "not/have not: missing reference".to_string(),
646 ));
647 }
648 Rule::sqrt_expr
649 | Rule::sin_expr
650 | Rule::cos_expr
651 | Rule::tan_expr
652 | Rule::asin_expr
653 | Rule::acos_expr
654 | Rule::atan_expr
655 | Rule::log_expr
656 | Rule::exp_expr => {
657 let operator = match node.as_rule() {
658 Rule::sqrt_expr => MathematicalOperator::Sqrt,
659 Rule::sin_expr => MathematicalOperator::Sin,
660 Rule::cos_expr => MathematicalOperator::Cos,
661 Rule::tan_expr => MathematicalOperator::Tan,
662 Rule::asin_expr => MathematicalOperator::Asin,
663 Rule::acos_expr => MathematicalOperator::Acos,
664 Rule::atan_expr => MathematicalOperator::Atan,
665 Rule::log_expr => MathematicalOperator::Log,
666 Rule::exp_expr => MathematicalOperator::Exp,
667 _ => {
668 return Err(LemmaError::Engine(
669 "Unknown mathematical operator".to_string(),
670 ))
671 }
672 };
673
674 for inner in node.clone().into_inner() {
675 if inner.as_rule() == Rule::arithmetic_expression
676 || inner.as_rule() == Rule::primary
677 {
678 let operand = parse_expression(inner, id_gen)?;
679 let kind =
680 ExpressionKind::MathematicalOperator(operator, Box::new(operand));
681 return Ok(traceable_expr(kind, &node, id_gen));
682 }
683 }
684 return Err(LemmaError::Engine(
685 "Mathematical operator missing operand".to_string(),
686 ));
687 }
688 _ => {}
689 }
690 }
691 Err(LemmaError::Engine("Empty logical expression".to_string()))
692}
693
694fn parse_comparable_base(
695 pair: Pair<Rule>,
696 id_gen: &mut ExpressionIdGenerator,
697) -> Result<Expression, LemmaError> {
698 let mut pairs = pair.clone().into_inner();
700
701 let arith_expr = parse_expression(
702 pairs.next().ok_or_else(|| {
703 LemmaError::Engine("No arithmetic expression in comparable_base".to_string())
704 })?,
705 id_gen,
706 )?;
707
708 if let Some(unit_pair) = pairs.next() {
710 if unit_pair.as_rule() == Rule::unit_word {
711 let target_unit = super::units::resolve_conversion_target(unit_pair.as_str())?;
712 let kind = ExpressionKind::UnitConversion(Box::new(arith_expr), target_unit);
713 return Ok(traceable_expr(kind, &pair, id_gen));
714 }
715 }
716
717 Ok(arith_expr)
719}