chasa/
cont.rs

1use crate::{
2    combi::{before, not_followed_by, tuple, Chain},
3    error::{self, MessageFrom},
4    input::{InputOnce, Save},
5    prim::{satisfy_map_once, satisfy_once, state_case_once, state_once},
6};
7
8use super::{
9    error::ParseError,
10    parser::{Args, ParserOnce},
11};
12
13pub struct Cont<'a, 'b, I: InputOnce, O, E: ParseError<I>, C, S>(pub(crate) Option<(O, Args<'a, 'b, I, E, C, S>)>);
14
15impl<'a, 'b, I: InputOnce, E: ParseError<I>, C, S> Args<'a, 'b, I, E, C, S> {
16    #[inline(always)]
17    pub fn to<O>(self, value: O) -> Cont<'a, 'b, I, O, E, C, S> {
18        Cont(Some((value, self)))
19    }
20    #[inline(always)]
21    pub fn done(self) -> Cont<'a, 'b, I, (), E, C, S> {
22        Cont(Some(((), self)))
23    }
24
25    #[inline(always)]
26    pub fn fail<M, O>(self, message: M) -> Cont<'a, 'b, I, O, E, C, S>
27    where
28        E: MessageFrom<M>,
29    {
30        if self.error.add(self.input.position(), self.input.position()) {
31            self.error.set(message)
32        }
33        Cont(None)
34    }
35
36    #[inline(always)]
37    pub fn fail_with_pos<M, O>(self, start: I::Position, end: I::Position, message: M) -> Cont<'a, 'b, I, O, E, C, S>
38    where
39        E: MessageFrom<M>,
40    {
41        if self.error.add(start, end) {
42            self.error.set(message)
43        }
44        Cont(None)
45    }
46
47    #[inline(always)]
48    pub fn state<O>(self, f: impl FnOnce(&mut S) -> O) -> Cont<'a, 'b, I, O, E, C, S> {
49        self.then(state_once(f))
50    }
51    #[inline(always)]
52    pub fn state_case<O>(
53        self, f: impl for<'c, 'd> FnOnce(&'c mut S, Args<'c, 'd, I, E, C, ()>) -> Cont<'c, 'd, I, O, E, C, ()>,
54    ) -> Cont<'a, 'b, I, O, E, C, S> {
55        self.then(state_case_once(f))
56    }
57
58    #[inline(always)]
59    pub fn satisfy(self, f: impl FnOnce(&I::Token) -> bool) -> Cont<'a, 'b, I, I::Token, E, C, S>
60    where
61        E: MessageFrom<error::Unexpected<error::Token<I::Token>>>,
62    {
63        self.then(satisfy_once(f))
64    }
65    #[inline(always)]
66    pub fn satisfy_map<O>(self, f: impl FnOnce(&I::Token) -> Option<O>) -> Cont<'a, 'b, I, O, E, C, S>
67    where
68        E: MessageFrom<error::Unexpected<error::Token<I::Token>>>,
69    {
70        self.then(satisfy_map_once(f))
71    }
72    #[inline(always)]
73    pub fn satisfy_cont<O>(
74        mut self, f: impl FnOnce(&I::Token, Args<'a, 'b, I, E, C, S>) -> Option<Cont<'a, 'b, I, O, E, C, S>>,
75    ) -> Cont<'a, 'b, I, O, E, C, S>
76    where
77        E: MessageFrom<error::Unexpected<error::Token<I::Token>>>,
78    {
79        match self.uncons() {
80            None => Cont(None),
81            Some((c, start)) => {
82                let Args { input, config, state, consume, error } = self;
83                // When `f` returns `None`, the reference to the `args` no longer exists, but the compiler takes the lifetime into account. To deal with this, unsafe is used. A better solution is sought.
84                let (input2, error2) = unsafe { (&mut *(input as *mut I), &mut *(error as *mut E)) };
85                match f(&c, Args { input, config, state, consume, error }) {
86                    Some(k) => k,
87                    None => {
88                        let end = input2.position();
89                        if error2.add(start, end) {
90                            error2.set(error::unexpected(error::token(c)));
91                        }
92                        Cont(None)
93                    },
94                }
95            },
96        }
97    }
98
99    #[inline(always)]
100    pub fn then<P: ParserOnce<I, O, E, C, S>, O>(mut self, p: P) -> Cont<'a, 'b, I, O, E, C, S> {
101        Cont(p.run_once(self.by_ref()).map(move |o| (o, self)))
102    }
103
104    #[inline(always)]
105    pub fn tuple<PS, O>(self, ps: PS) -> Cont<'a, 'b, I, O, E, C, S>
106    where
107        Chain<PS>: ParserOnce<I, O, E, C, S>,
108    {
109        self.then(tuple(ps))
110    }
111
112    #[inline(always)]
113    pub fn before<P: ParserOnce<I, O, E, C, S>, O>(self, p: P) -> Cont<'a, 'b, I, O, E, C, S>
114    where
115        I: Save,
116        S: Save,
117    {
118        self.then(before(p))
119    }
120
121    #[inline(always)]
122    pub fn not_followed_by<P: ParserOnce<I, O, E, C, S>, O, L>(self, p: P, label: L) -> Cont<'a, 'b, I, (), E, C, S>
123    where
124        E: MessageFrom<error::Unexpected<error::Format<L>>>,
125        I: Save,
126        S: Save,
127    {
128        self.then(not_followed_by(p, label))
129    }
130
131    #[inline(always)]
132    pub fn config<O>(self, f: impl FnOnce(&'a C, Self) -> Cont<'a, 'b, I, O, E, C, S>) -> Cont<'a, 'b, I, O, E, C, S> {
133        f(self.config, self)
134    }
135}
136
137impl<'a, 'b, I: InputOnce, O, E: ParseError<I>, C, S> Cont<'a, 'b, I, O, E, C, S> {
138    #[inline(always)]
139    pub fn ignore(self) -> Option<Args<'a, 'b, I, E, C, S>> {
140        self.0.map(|x| x.1)
141    }
142
143    #[inline(always)]
144    pub fn to<O2>(self, value: O2) -> Cont<'a, 'b, I, O2, E, C, S> {
145        self.case(|_, k| k.to(value))
146    }
147    #[inline(always)]
148    pub fn case<T>(
149        self, f: impl FnOnce(O, Args<'a, 'b, I, E, C, S>) -> Cont<'a, 'b, I, T, E, C, S>,
150    ) -> Cont<'a, 'b, I, T, E, C, S> {
151        Cont(self.0.and_then(|(o, k)| f(o, k).0))
152    }
153    #[inline(always)]
154    pub fn bind<F: FnOnce(O) -> P, P: ParserOnce<I, O2, E, C, S>, O2>(self, f: F) -> Cont<'a, 'b, I, O2, E, C, S> {
155        self.case(|o, k| k.then(f(o)))
156    }
157
158    #[inline(always)]
159    pub fn map<T>(self, f: impl FnOnce(O) -> T) -> Cont<'a, 'b, I, T, E, C, S> {
160        Cont(self.0.map(|(o, k)| (f(o), k)))
161    }
162    #[inline(always)]
163    pub fn and<P: ParserOnce<I, O2, E, C, S>, O2>(self, p: P) -> Cont<'a, 'b, I, (O, O2), E, C, S> {
164        self.case(|o1, k| k.then(p).map(|o2| (o1, o2)))
165    }
166    #[inline(always)]
167    pub fn left<P: ParserOnce<I, O2, E, C, S>, O2>(self, p: P) -> Cont<'a, 'b, I, O, E, C, S> {
168        self.case(|o, k| k.then(p).to(o))
169    }
170    #[inline(always)]
171    pub fn right<P: ParserOnce<I, O2, E, C, S>, O2>(self, p: P) -> Cont<'a, 'b, I, O2, E, C, S> {
172        self.case(|_, k| k.then(p))
173    }
174}