combine/parser/
error.rs

1//! Parsers which cause errors or modifies the returned error on parse failure.
2
3use crate::{
4    error::{
5        ErrorInfo, ParseError,
6        ParseResult::{self, *},
7        StreamError, Tracked,
8    },
9    lib::marker::PhantomData,
10    parser::ParseMode,
11    Parser, Stream, StreamOnce,
12};
13
14#[derive(Clone)]
15pub struct Unexpected<I, T, E>(E, PhantomData<fn(I) -> (I, T)>)
16where
17    I: Stream;
18impl<Input, T, E> Parser<Input> for Unexpected<Input, T, E>
19where
20    Input: Stream,
21    E: for<'s> ErrorInfo<'s, Input::Token, Input::Range>,
22{
23    type Output = T;
24    type PartialState = ();
25    #[inline]
26    fn parse_lazy(&mut self, input: &mut Input) -> ParseResult<T, <Input as StreamOnce>::Error> {
27        PeekErr(<Input as StreamOnce>::Error::empty(input.position()).into())
28    }
29    fn add_error(&mut self, errors: &mut Tracked<<Input as StreamOnce>::Error>) {
30        errors.error.add(StreamError::unexpected(&self.0));
31    }
32}
33/// Always fails with `message` as an unexpected error.
34/// Never consumes any input.
35///
36/// Has `()` the output type
37///
38/// ```
39/// # extern crate combine;
40/// # use combine::*;
41/// # use combine::error::StreamError;
42/// # fn main() {
43/// let result = unexpected("token")
44///     .easy_parse("a");
45/// assert!(result.is_err());
46/// assert!(
47///     result.err()
48///         .unwrap()
49///         .errors
50///         .iter()
51///         .any(|m| *m == StreamError::unexpected("token"))
52/// );
53/// # }
54/// ```
55pub fn unexpected<Input, S>(message: S) -> Unexpected<Input, (), S>
56where
57    Input: Stream,
58    S: for<'s> ErrorInfo<'s, Input::Token, Input::Range>,
59{
60    unexpected_any(message)
61}
62
63/// Always fails with `message` as an unexpected error.
64/// Never consumes any input.
65///
66/// May have anything as the output type but must be used such that the output type can inferred.
67/// The `unexpected` parser can be used if the output type does not matter
68///
69/// ```
70/// # extern crate combine;
71/// # use combine::*;
72/// # use combine::parser::error::unexpected_any;
73/// # use combine::error::StreamError;
74/// # fn main() {
75/// let result = token('b').or(unexpected_any("token"))
76///     .easy_parse("a");
77/// assert!(result.is_err());
78/// assert!(
79///     result.err()
80///         .unwrap()
81///         .errors
82///         .iter()
83///         .any(|m| *m == StreamError::unexpected("token"))
84/// );
85/// # }
86/// ```
87pub fn unexpected_any<Input, S, T>(message: S) -> Unexpected<Input, T, S>
88where
89    Input: Stream,
90    S: for<'s> ErrorInfo<'s, Input::Token, Input::Range>,
91{
92    Unexpected(message, PhantomData)
93}
94
95#[derive(Clone)]
96pub struct Message<P, S>(P, S);
97impl<Input, P, S> Parser<Input> for Message<P, S>
98where
99    Input: Stream,
100    P: Parser<Input>,
101    S: for<'s> ErrorInfo<'s, Input::Token, Input::Range>,
102{
103    type Output = P::Output;
104    type PartialState = P::PartialState;
105
106    parse_mode!(Input);
107    #[inline]
108    fn parse_mode_impl<M>(
109        &mut self,
110        mode: M,
111        input: &mut Input,
112        state: &mut Self::PartialState,
113    ) -> ParseResult<Self::Output, <Input as StreamOnce>::Error>
114    where
115        M: ParseMode,
116    {
117        match self.0.parse_mode(mode, input, state) {
118            CommitOk(x) => CommitOk(x),
119            PeekOk(x) => PeekOk(x),
120
121            // The message should always be added even if some input was committed before failing
122            CommitErr(mut err) => {
123                err.add_message(&self.1);
124                CommitErr(err)
125            }
126
127            // The message will be added in `add_error`
128            PeekErr(err) => PeekErr(err),
129        }
130    }
131
132    fn add_error(&mut self, errors: &mut Tracked<<Input as StreamOnce>::Error>) {
133        self.0.add_error(errors);
134        errors.error.add_message(&self.1);
135    }
136
137    forward_parser!(Input, parser_count add_committed_expected_error, 0);
138}
139
140/// Equivalent to [`p1.message(msg)`].
141///
142/// [`p1.message(msg)`]: ../trait.Parser.html#method.message
143pub fn message<Input, P, S>(p: P, msg: S) -> Message<P, S>
144where
145    P: Parser<Input>,
146    Input: Stream,
147    S: for<'s> ErrorInfo<'s, Input::Token, Input::Range>,
148{
149    Message(p, msg)
150}
151
152#[derive(Clone)]
153pub struct Expected<P, S>(P, S);
154impl<Input, P, S> Parser<Input> for Expected<P, S>
155where
156    P: Parser<Input>,
157    Input: Stream,
158    S: for<'s> ErrorInfo<'s, Input::Token, Input::Range>,
159{
160    type Output = P::Output;
161    type PartialState = P::PartialState;
162
163    parse_mode!(Input);
164    #[inline]
165    fn parse_mode_impl<M>(
166        &mut self,
167        mode: M,
168        input: &mut Input,
169        state: &mut Self::PartialState,
170    ) -> ParseResult<Self::Output, <Input as StreamOnce>::Error>
171    where
172        M: ParseMode,
173    {
174        self.0.parse_mode(mode, input, state)
175    }
176
177    fn add_error(&mut self, errors: &mut Tracked<<Input as StreamOnce>::Error>) {
178        ParseError::set_expected(errors, StreamError::expected(&self.1), |errors| {
179            self.0.add_error(errors);
180        })
181    }
182
183    forward_parser!(Input, parser_count add_committed_expected_error, 0);
184}
185
186/// Equivalent to [`p.expected(info)`].
187///
188/// [`p.expected(info)`]: ../trait.Parser.html#method.expected
189pub fn expected<Input, P, S>(p: P, info: S) -> Expected<P, S>
190where
191    P: Parser<Input>,
192    Input: Stream,
193    S: for<'s> ErrorInfo<'s, Input::Token, Input::Range>,
194{
195    Expected(p, info)
196}
197
198#[derive(Clone)]
199pub struct Silent<P>(P);
200impl<Input, P> Parser<Input> for Silent<P>
201where
202    P: Parser<Input>,
203    Input: Stream,
204{
205    type Output = P::Output;
206    type PartialState = P::PartialState;
207
208    parse_mode!(Input);
209    #[inline]
210    fn parse_mode_impl<M>(
211        &mut self,
212        mode: M,
213        input: &mut Input,
214        state: &mut Self::PartialState,
215    ) -> ParseResult<Self::Output, <Input as StreamOnce>::Error>
216    where
217        M: ParseMode,
218    {
219        self.0.parse_mode(mode, input, state).map_err(|mut err| {
220            err.clear_expected();
221            err
222        })
223    }
224
225    fn add_error(&mut self, _errors: &mut Tracked<<Input as StreamOnce>::Error>) {}
226
227    fn add_committed_expected_error(
228        &mut self,
229        _errors: &mut Tracked<<Input as StreamOnce>::Error>,
230    ) {
231    }
232
233    forward_parser!(Input, parser_count, 0);
234}
235
236/// Equivalent to [`p.silent()`].
237///
238/// [`p.silent()`]: ../trait.Parser.html#method.silent
239pub fn silent<Input, P>(p: P) -> Silent<P>
240where
241    P: Parser<Input>,
242    Input: Stream,
243{
244    Silent(p)
245}