1use crate::parser::{ParseResult, Parser};
2use crate::state::State;
3
4use functionality::prelude::*;
5
6impl<'a, T: 'a, F: 'a, E: 'a> Parser<'a, T, E, F> {
7 pub fn of_bool(value: bool) -> Parser<'a, T, E, F>
8 where
9 T: Default + Clone,
10 F: Default + Clone,
11 {
12 if value {
13 Parser::ret(T::default())
14 } else {
15 Parser::fail(F::default())
16 }
17 }
18}
19
20#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
21pub struct EofFailure;
22
23impl<'a, E: 'a> Parser<'a, char, E, EofFailure> {
24 pub fn char() -> Parser<'a, char, E, EofFailure> {
25 Parser::from_fn(|state| {
26 if state.rest().is_empty() {
27 ParseResult::Fail(EofFailure, state.pos)
28 } else {
29 let ch = state.rest().chars().next().unwrap();
30 let new_pos = if ch == '\n' {
31 state.pos.down()
32 } else {
33 state.pos.right()
34 };
35 ParseResult::Ok(ch, new_pos)
36 }
37 })
38 }
39}
40
41impl<'a, F: Clone + Default + 'a, E: 'a> Parser<'a, char, E, F> {
42 pub fn char_eq(ch: char) -> Parser<'a, char, E, F> {
43 Parser::char()
44 .map_fail(|_| F::default())
45 .filter(move |&c| c == ch)
46 }
47}
48
49#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
50pub struct NotWhitespace;
51
52impl<'a, E: 'a> Parser<'a, char, E, NotWhitespace> {
53 pub fn whitespace() -> Parser<'a, char, E, NotWhitespace> {
54 Parser::char()
55 .map_fail(|_| NotWhitespace)
56 .filter(|c| c.is_whitespace())
57 }
58}
59
60impl<'a, F: 'a, E: 'a> Parser<'a, (), E, F> {
61 pub fn skip_whitespace() -> Parser<'a, (), E, F> {
62 Parser::whitespace().repeat_0().map(|_| ())
63 }
64}
65
66#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
67pub struct NotALetter;
68
69impl<'a, E: 'a> Parser<'a, char, E, NotALetter> {
70 pub fn letter() -> Parser<'a, char, E, NotALetter> {
71 Parser::char()
72 .map_fail(|_| NotALetter)
73 .filter(|c| c.is_ascii_alphabetic())
74 }
75}
76
77#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
78pub struct NotADigit;
79
80impl<'a, E: 'a> Parser<'a, char, E, NotADigit> {
81 pub fn digit() -> Parser<'a, char, E, NotADigit> {
82 Parser::char()
83 .map_fail(|_| NotADigit)
84 .filter(|c| c.is_ascii_digit())
85 }
86}
87
88#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
89pub struct NotFound;
90
91impl<'a, E: 'a> Parser<'a, char, E, NotFound> {
92 pub fn eof() -> Parser<'a, (), E, NotFound> {
93 Parser::state()
94 .map(|state| state.rest().is_empty())
95 .and_then(Parser::of_bool)
96 }
97
98 pub fn expect_string(expected: &'static str) -> Parser<'a, (), E, NotFound> {
99 Parser::state()
100 .map(move |state: State| state.rest().starts_with(expected))
101 .and_then(Parser::of_bool)
102 .and_then(move |()| {
103 Parser::from_fn(move |state| {
104 assert!(expected.chars().all(|c| c != '\n'));
106 let mut new_pos = state.pos;
107 for _ in 0..expected.len() {
108 new_pos = new_pos.right();
109 }
110 ParseResult::Ok((), new_pos)
111 })
112 })
113 }
114}
115
116impl<'a, T, F, E> Parser<'a, T, E, F> {
117 pub fn maybe<G>(self) -> Parser<'a, Option<T>, E, G>
119 where
120 T: 'a,
121 E: 'a,
122 F: 'a,
123 {
124 let name = format!("maybe({})", &self.name);
125 self.map(Some)
126 .or(Parser::<_, _, ()>::ret_with(|| None))
127 .map_fail(|()| panic!("maybe should not fail"))
128 .with_name(name)
129 }
130
131 pub fn repeat_0<G>(self) -> Parser<'a, Vec<T>, E, G>
133 where
134 T: Clone + 'a,
135 E: 'a,
136 F: 'a,
137 G: 'a,
138 {
139 let name = format!("repeat_0({})", &self.name);
140 self.clone()
141 .and_then(move |x| {
142 self.clone()
143 .repeat_0()
144 .map(move |xs| vec![x.clone()].mutate(|v| v.extend(xs)))
145 })
146 .or(Parser::<_, _, G>::ret_with(Vec::new))
147 .map_fail(|(_, g)| g)
148 .with_name(name)
149 }
150
151 pub fn repeat_1(self) -> Parser<'a, Vec<T>, E, F>
153 where
154 T: Clone + 'a,
155 E: 'a,
156 F: 'a,
157 {
158 let name = format!("repeat_1({})", &self.name);
159 self.clone()
160 .and_then(move |x| {
161 self.clone()
162 .repeat_0()
163 .map(move |xs| vec![x.clone()].mutate(|v| v.extend(xs)))
164 })
165 .with_name(name)
166 }
167}
168
169impl<'a, T, F, E> Parser<'a, T, E, F> {
170 #[allow(clippy::should_implement_trait)]
171 pub fn not<G>(self) -> Parser<'a, (), E, G>
172 where
173 T: 'a,
174 E: 'a,
175 F: 'a,
176 G: Default + 'a,
177 {
178 #[rustfmt::skip]
179 #[derive(Debug, Clone)]
180 enum ShouldFail { Yes, No }
181
182 let name = format!("not({})", &self.name);
183 self.map_fail(|_| ShouldFail::No)
184 .and_then(|_| Parser::fail(ShouldFail::Yes))
185 .and_then_fail(|f| match f {
186 ShouldFail::Yes => Parser::fail_with(|| G::default()),
187 ShouldFail::No => Parser::ret(()),
188 })
189 .with_name(name)
190 }
191}