lemma/parser/
facts.rs

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}