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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
use crate::{Spanned, Token};
use alloc::{string::String, vec::Vec};
use chumsky::prelude::*;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
pub type Path<T> = Vec<(Part<Spanned<T>>, Opt)>;
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug)]
pub enum Part<I> {
Index(I),
Range(Option<I>, Option<I>),
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Copy, Clone, Debug)]
pub enum Opt {
Optional,
Essential,
}
fn opt() -> impl Parser<Token, Opt, Error = Simple<Token>> + Clone {
just(Token::Ctrl('?')).or_not().map(|q| match q {
Some(_) => Opt::Optional,
None => Opt::Essential,
})
}
pub(crate) fn index<T: From<String>>(
) -> impl Parser<Token, (Part<Spanned<T>>, Opt), Error = Simple<Token>> + Clone {
filter_map(|span, tok| match tok {
Token::Ident(id) | Token::Str(id) => Ok(Part::Index((T::from(id), span))),
_ => Err(Simple::expected_input_found(span, Vec::new(), Some(tok))),
})
.then(opt())
}
pub(crate) fn path<T, P>(expr: P) -> impl Parser<Token, Path<T>, Error = P::Error> + Clone
where
T: From<String>,
P: Parser<Token, Spanned<T>, Error = Simple<Token>> + Clone,
{
let range = {
let colon = just(Token::Ctrl(':'));
let e2 = colon.clone().ignore_then(expr.clone().or_not());
let starts_with_expr = expr.clone().then(e2.or_not()).map(|(e1, e2)| match e2 {
None => Part::Index(e1),
Some(e2) => Part::Range(Some(e1), e2),
});
let starts_with_colon = colon
.ignore_then(expr)
.map(|e2| Part::Range(None, Some(e2)));
starts_with_expr
.or(starts_with_colon)
.or_not()
.map(|o| o.unwrap_or(Part::Range(None, None)))
};
let ranges = range
.delimited_by(just(Token::Ctrl('[')), just(Token::Ctrl(']')))
.then(opt())
.repeated();
let dot_id = just(Token::Dot).ignore_then(index());
ranges
.clone()
.chain(dot_id.chain(ranges).repeated().flatten())
.collect()
}
impl Opt {
pub fn fail<T, E>(self, x: T, f: impl FnOnce(T) -> E) -> Result<T, E> {
match self {
Self::Optional => Ok(x),
Self::Essential => Err(f(x)),
}
}
pub fn collect<T, E>(self, iter: impl Iterator<Item = Result<T, E>>) -> Result<Vec<T>, E> {
match self {
Self::Optional => Ok(iter.filter_map(|x| x.ok()).collect()),
Self::Essential => iter.collect(),
}
}
}