summaryrefslogtreecommitdiff
path: root/tests/sexpr.rs
blob: a3783f049acc0238b6a2ebfdc960946f3d745045 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#![allow(dead_code)]

use mon::{
    Parser, ParserIter, ascii_alpha1, ascii_alphanumeric, ascii_alphanumeric1, ascii_numeric1,
    ascii_whitespace1, input::InputIter, tag,
};

#[derive(Debug)]
enum Sexpr {
    List(Vec<Sexpr>),
    Atom(String),
    String(String),
    Int(i64),
}

fn atom<'a>() -> impl Parser<&'a str, Output = Sexpr> {
    ascii_alpha1()
        .and(ascii_alphanumeric().repeated().many())
        .recognize()
        .map(|output: &str| Sexpr::Atom(output.to_string()))
}

fn string<'a>() -> impl Parser<&'a str, Output = Sexpr> {
    ascii_alphanumeric1()
        .delimited_by(tag("\""), tag("\""))
        .map(|output: &str| Sexpr::String(output.to_string()))
}

fn int<'a>() -> impl Parser<&'a str, Output = Sexpr> {
    ascii_numeric1().map(|output: &str| Sexpr::Int(output.parse().unwrap()))
}

// Recursive parsers must avoid an infinite loop, you can do this
// by returning a closure that accepts an InputIter and returns ParserResult.
fn sexpr<'a>() -> impl Parser<&'a str, Output = Sexpr> {
    |it| {
        sexpr()
            .separated_by(ascii_whitespace1())
            .many()
            .delimited_by(tag("("), tag(")"))
            .map(|output| Sexpr::List(output))
            .or(atom())
            .or(string())
            .or(int())
            .parse(it)
    }
}

#[test]
fn test_atom() {
    let input = "atom";
    let it = InputIter::new(input);

    atom().check_finished(it).unwrap();
}

#[test]
fn test_string() {
    let input = r#""string""#;
    let it = InputIter::new(input);

    string().check_finished(it).unwrap()
}

#[test]
fn test_sexpr() {
    let input = r#"(let ((a "hello") (b 2)))"#;
    let it = InputIter::new(input);

    dbg!(sexpr().parse_finished(it).unwrap());
}