1
#![forbid(unsafe_code)]
2
#![allow(clippy::result_large_err)]
3

            
4
use pest_derive::Parser;
5

            
6
use merc_pest_consume::Error;
7
use merc_pest_consume::match_nodes;
8

            
9
use crate::ATerm;
10
use crate::Symbol;
11

            
12
#[derive(Parser)]
13
#[grammar = "term_grammar.pest"]
14
pub struct TermParser;
15

            
16
type ParseResult<T> = std::result::Result<T, Error<Rule>>;
17
type ParseNode<'i> = merc_pest_consume::Node<'i, Rule, ()>;
18

            
19
/// Parse a term from a string.
20
///
21
/// TODO: Parse integer terms and aterm list as in the mCRL2 toolset.
22
///
23
/// Grammar:  f(t_1, ..., t_n) | c
24
#[merc_pest_consume::parser]
25
impl TermParser {
26
    pub fn TermSpec(spec: ParseNode) -> ParseResult<ATerm> {
27
        TermParser::Term(spec.children().next().unwrap())
28
    }
29

            
30
    fn Id(input: ParseNode) -> Result<String, Error<Rule>> {
31
        Ok(input.as_str().to_string())
32
    }
33

            
34
    fn Term(term: ParseNode) -> Result<ATerm, Error<Rule>> {
35
        match_nodes!(term.into_children();
36
            [Id(identifier)] => {
37
                let symbol = Symbol::new(identifier, 0);
38

            
39
                Ok(ATerm::constant(&symbol))
40
            },
41
            [Id(identifier), Args(args)] => {
42
                let symbol = Symbol::new(identifier, args.len());
43

            
44
                Ok(ATerm::with_iter(&symbol, args))
45
            }
46
        )
47
    }
48

            
49
    fn Args(args: ParseNode) -> Result<Vec<ATerm>, Error<Rule>> {
50
        match_nodes!(args.into_children();
51
            [Term(term)..] => {
52
                Ok(term.collect())
53
            }
54
        )
55
    }
56
}
57

            
58
#[cfg(test)]
59
mod tests {
60
    use pest::Parser;
61

            
62
    use super::*;
63

            
64
    #[test]
65
1
    fn test_parse_term() {
66
1
        let term = "f(a, b)";
67

            
68
1
        let result = TermParser::parse(Rule::TermSpec, term).unwrap();
69
1
        print!("{}", result);
70
1
    }
71
}