1use crate::error::LemmaError;
2use crate::parser::Rule;
3use crate::semantic::*;
4use pest::iterators::Pair;
5
6pub(crate) fn parse_fact_definition(pair: Pair<Rule>) -> Result<LemmaFact, LemmaError> {
7 let span = crate::ast::Span::from_pest_span(pair.as_span());
8 let mut fact_name = None;
9 let mut fact_value = None;
10
11 for inner_pair in pair.into_inner() {
12 match inner_pair.as_rule() {
13 Rule::fact_name => fact_name = Some(inner_pair.as_str().to_string()),
14 Rule::fact_value => fact_value = Some(parse_fact_value(inner_pair)?),
15 _ => {}
16 }
17 }
18
19 let name = fact_name.ok_or_else(|| {
20 LemmaError::Engine("Grammar error: fact_definition missing fact_name".to_string())
21 })?;
22 let value = fact_value.ok_or_else(|| {
23 LemmaError::Engine("Grammar error: fact_definition missing fact_value".to_string())
24 })?;
25
26 Ok(LemmaFact::new(crate::FactType::Local(name), value).with_span(span))
27}
28
29pub(crate) fn parse_fact_override(pair: Pair<Rule>) -> Result<LemmaFact, LemmaError> {
30 let span = crate::ast::Span::from_pest_span(pair.as_span());
31 let mut fact_override_name = None;
32 let mut fact_value = None;
33
34 for inner_pair in pair.into_inner() {
35 match inner_pair.as_rule() {
36 Rule::fact_override_name => {
37 fact_override_name = Some(parse_fact_override_name(inner_pair)?)
38 }
39 Rule::fact_value => fact_value = Some(parse_fact_value(inner_pair)?),
40 _ => {}
41 }
42 }
43
44 let override_ref = fact_override_name.ok_or_else(|| {
45 LemmaError::Engine("Grammar error: fact_override missing fact_override_name".to_string())
46 })?;
47 let value = fact_value.ok_or_else(|| {
48 LemmaError::Engine("Grammar error: fact_override missing fact_value".to_string())
49 })?;
50
51 Ok(LemmaFact::new(crate::FactType::Foreign(override_ref), value).with_span(span))
52}
53
54fn parse_fact_override_name(pair: Pair<Rule>) -> Result<crate::ForeignFact, LemmaError> {
55 let mut reference = Vec::new();
56 for inner_pair in pair.into_inner() {
57 if inner_pair.as_rule() == Rule::label {
58 reference.push(inner_pair.as_str().to_string());
59 }
60 }
61 if reference.is_empty() {
62 return Err(LemmaError::Engine(
63 "Grammar error: fact_override_name has no labels".to_string(),
64 ));
65 }
66 Ok(crate::ForeignFact { reference })
67}
68
69fn parse_fact_value(pair: Pair<Rule>) -> Result<FactValue, LemmaError> {
70 for inner_pair in pair.into_inner() {
71 match inner_pair.as_rule() {
72 Rule::type_annotation => return parse_fact_type_annotation(inner_pair),
73 Rule::document_reference => return parse_fact_document_reference(inner_pair),
74 Rule::literal => return parse_fact_literal(inner_pair),
75 _ => {}
76 }
77 }
78 Err(LemmaError::Engine(
79 "Grammar error: fact_value must contain literal, type_annotation, or document_reference"
80 .to_string(),
81 ))
82}
83
84fn parse_fact_type_annotation(pair: Pair<Rule>) -> Result<FactValue, LemmaError> {
85 for inner_pair in pair.into_inner() {
86 if inner_pair.as_rule() == Rule::type_name {
87 if let Some(type_inner) = inner_pair.into_inner().next() {
88 let lemma_type = match type_inner.as_rule() {
89 Rule::text_type => LemmaType::Text,
90 Rule::number_type => LemmaType::Number,
91 Rule::date_type => LemmaType::Date,
92 Rule::boolean_type => LemmaType::Boolean,
93 Rule::regex_type => LemmaType::Regex,
94 Rule::percentage_type => LemmaType::Percentage,
95 Rule::weight_type => LemmaType::Mass,
96 Rule::length_type => LemmaType::Length,
97 Rule::volume_type => LemmaType::Volume,
98 Rule::duration_type => LemmaType::Duration,
99 Rule::temperature_type => LemmaType::Temperature,
100 Rule::power_type => LemmaType::Power,
101 Rule::energy_type => LemmaType::Energy,
102 Rule::force_type => LemmaType::Force,
103 Rule::pressure_type => LemmaType::Pressure,
104 Rule::frequency_type => LemmaType::Frequency,
105 Rule::data_size_type => LemmaType::Data,
106 Rule::money_type => LemmaType::Money,
107 _ => {
108 return Err(LemmaError::Engine(format!(
109 "Unknown type rule: {:?}",
110 type_inner.as_rule()
111 )))
112 }
113 };
114 return Ok(FactValue::TypeAnnotation(TypeAnnotation::LemmaType(
115 lemma_type,
116 )));
117 }
118 }
119 }
120 Err(LemmaError::Engine(
121 "Grammar error: type_annotation must contain type_name".to_string(),
122 ))
123}
124
125fn parse_fact_document_reference(pair: Pair<Rule>) -> Result<FactValue, LemmaError> {
126 let doc_name = pair
127 .into_inner()
128 .next()
129 .ok_or_else(|| {
130 LemmaError::Engine("Grammar error: document_reference must contain label".to_string())
131 })?
132 .as_str()
133 .to_string();
134
135 Ok(FactValue::DocumentReference(doc_name))
136}
137
138fn parse_fact_literal(pair: Pair<Rule>) -> Result<FactValue, LemmaError> {
139 let literal_value =
140 crate::parser::literals::parse_literal(pair.into_inner().next().ok_or_else(|| {
141 LemmaError::Engine("Grammar error: literal must contain a literal value".to_string())
142 })?)?;
143 Ok(FactValue::Literal(literal_value))
144}