1
use pest::Parser;
2
use pest_consume::match_nodes;
3
use pest_consume::Error;
4

            
5
use crate::ast::Mcrl2Specification;
6
use crate::parse_sortexpr;
7
use crate::DisplayPair;
8
use crate::IdsDecl;
9
use crate::Mcrl2Parser;
10
use crate::Rule;
11
use crate::SortExpression;
12

            
13

            
14
/// Parses the given mCRL2 specification into an AST.
15
170
pub fn parse_mcrl2_specification(spec: &str) -> std::result::Result<Mcrl2Specification, Box<dyn std::error::Error>> {
16
170
    pest::set_error_detail(true);
17

            
18
170
    let mut result = Mcrl2Parser::parse(Rule::MCRL2Spec, spec)?;
19
170
    let root = result.next().unwrap();
20
170
    println!("{}", DisplayPair(root.clone()));
21
170

            
22
170
    //Mcrl2Parser::MCRL2Spec(ParseNode::new(root)).map_err(|e| e.into())
23
170
    Ok(Mcrl2Specification {
24
170
        map: vec![]
25
170
    })
26
170
}
27

            
28
type ParseResult<T> = std::result::Result<T, Error<Rule>>;
29
type ParseNode<'i> = pest_consume::Node<'i, Rule, ()>;
30

            
31
#[pest_consume::parser]
32
impl Mcrl2Parser {
33
    fn MCRL2Spec(spec: ParseNode) -> ParseResult<Mcrl2Specification> {
34
        let mut map = Vec::new();
35

            
36
        for child in spec.into_children() {
37
            match child.as_rule() {
38
                Rule::MapSpec => {
39
                    map.append(&mut Mcrl2Parser::MapSpec(child)?);
40
                },
41
                _ => {
42

            
43
                }
44
            }
45
        }
46

            
47
        Ok(Mcrl2Specification {
48
            map
49
        })
50
    }
51

            
52
    fn MapSpec(spec: ParseNode) -> ParseResult<Vec<IdsDecl>> {
53
        let mut ids = Vec::new();
54
        
55
        for decl in spec.into_children() {
56
            ids.push(Mcrl2Parser::IdsDecl(decl)?);
57
        }
58

            
59
        Ok(ids)
60
    }
61

            
62
    fn IdsDecl(decl: ParseNode) -> ParseResult<IdsDecl> {
63
        let span = decl.as_span();
64
        match_nodes!(decl.into_children();
65
            [IdList(identifiers), SortExpr(sort)] => {
66
                return Ok(IdsDecl { identifiers, sort, span: span.into() });
67
            },
68
        );
69
    }
70

            
71
    fn IdList(list: ParseNode) -> ParseResult<Vec<String>> {
72
        Ok(list.into_children().map(|i| {
73
            i.as_str().to_string()
74
        }).collect())
75
    }
76

            
77
    fn SortExpr(expr: ParseNode) -> ParseResult<SortExpression> {
78
        Ok(parse_sortexpr(expr.children().as_pairs().clone()))
79
    }
80

            
81
    fn EOI(_input: ParseNode) -> ParseResult<()> {
82
        Ok(())
83
    }
84
}
85

            
86

            
87
#[cfg(test)]
88
mod tests {
89
    use super::*;
90

            
91
    #[test]
92
1
    fn test_parse_term() {
93
        use indoc::indoc;
94

            
95
1
        let spec: &str = indoc! {"map
96
1
            f: Boolean # Int -> Int -> Bool;
97
1
        "};
98
1

            
99
1
        println!("{}", parse_mcrl2_specification(spec).unwrap());
100
1
    }
101
}