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
use crate::{
ast::{ErrorToken, Expression},
parser::{
identifier,
utils::{LocatedSpan, ToRange},
IResult,
},
};
use nom::{branch::alt, bytes::complete::take_till1, combinator::map};
use std::ops::Range;
#[derive(Debug, PartialEq)]
pub struct Error(pub Range<usize>, pub String);
pub(crate) fn expect<'a, F, E, T>(
parser: F,
error_msg: E,
) -> impl Fn(LocatedSpan<'a>) -> IResult<Option<T>>
where
F: Fn(LocatedSpan<'a>) -> IResult<T>,
E: ToString,
{
move |input| match parser(input) {
Ok((remaining, out)) => Ok((remaining, Some(out))),
Err(nom::Err::Error(err)) | Err(nom::Err::Failure(err)) => {
let input = err.input;
let err = Error(input.to_range(), error_msg.to_string());
input.extra.report_error(err);
Ok((input, None))
}
Err(err) => Err(err),
}
}
pub(crate) fn error(input: LocatedSpan) -> IResult<Expression> {
alt((
map(identifier, |span: LocatedSpan| {
span.extra.report_error(Error(
span.to_range(),
format!("unexpected `{}`", span.fragment()),
));
Expression::Error(ErrorToken::Identifier(span.to_string()))
}),
map(take_till1(|c| c == ')' || c == ' '), |span: LocatedSpan| {
span.extra.report_error(Error(
span.to_range(),
format!("unexpected `{}`", span.fragment()),
));
Expression::Error(ErrorToken::Unexpected)
}),
))(input)
}