1
use std::sync::LazyLock;
2

            
3
use pest::iterators::Pairs;
4
use pest::pratt_parser::Assoc::Left;
5
use pest::pratt_parser::Assoc::Right;
6
use pest::pratt_parser::Op;
7
use pest::pratt_parser::PrattParser;
8

            
9
use crate::ast::SortExpression;
10
use crate::ComplexSort;
11
use crate::Rule;
12
use crate::Sort;
13

            
14
static SORT_PRATT_PARSER: LazyLock<PrattParser<Rule>> = LazyLock::new(|| {
15
    // Precedence is defined lowest to highest
16
    PrattParser::new()
17
        // Sort operators
18
        .op(Op::infix(Rule::SortExprFunction, Left))
19
        .op(Op::infix(Rule::SortExprProduct, Right))
20
});
21

            
22
pub fn parse_sortexpr(pairs: Pairs<Rule>) -> SortExpression {
23
    SORT_PRATT_PARSER
24
        .map_primary(|primary|
25
        {
26
           match primary.as_rule() {
27
                Rule::SortExprAtom => {
28
                    let inner = primary.into_inner().next().unwrap();
29
                    match inner.as_rule() {
30
                        Rule::Id => SortExpression::Reference(inner.as_str().to_string()),
31
                        Rule::SortExprBool => SortExpression::Simple(Sort::Bool),
32
                        Rule::SortExprInt => SortExpression::Simple(Sort::Int),
33
                        Rule::SortExprPos => SortExpression::Simple(Sort::Pos),
34
                        Rule::SortExprNat => SortExpression::Simple(Sort::Nat),
35
                        Rule::SortExprReal => SortExpression::Simple(Sort::Real),
36
                        Rule::SortExprList => SortExpression::Complex(ComplexSort::List, Box::new(parse_sortexpr(inner.into_inner()))),
37
                        _ => unreachable!("Unknown SortExprAtom {inner:?}"),
38
                    }
39
                },
40
                _ => unreachable!("{primary:?}"),
41
           }
42
        })
43
        .map_infix(|lhs, op, rhs| 
44
        {
45
            match op.as_rule() {
46
                Rule::SortExprFunction => SortExpression::Function {
47
                    domain: Box::new(lhs),
48
                    range: Box::new(rhs),
49
                },
50
                Rule::SortExprProduct => SortExpression::Product {
51
                    lhs: Box::new(lhs),
52
                    rhs: Box::new(rhs),
53
                },
54
                _ => unreachable!(),
55
            }
56
        })
57
        .parse(pairs)
58
}
59

            
60

            
61
// #[cfg(test)]
62
// mod tests {
63
//     use pest::Parser;
64

            
65
//     use crate::Mcrl2Parser;
66

            
67
//     use super::*;
68

            
69
//     #[test]
70
//     fn test_precedence() {
71
//         let term = "List(Data)";
72

            
73
//         let result = Mcrl2Parser::parse(Rule::SortExpr, term).unwrap();
74
//         print!("{}", parse_sortexpr(result));
75
//     }
76
// }