1use std::borrow::Cow;
3use std::marker::PhantomData;
4
5use crate::syntax::{Epsilon, Metadata, MetadataBuilder, Result as SynResult};
6use crate::{Lexicon, Parser, Produce, Production, ToSpan};
7
8use super::Node;
9
10#[doc(hidden)]
12pub struct OptionProd<T: Production>(PhantomData<T>);
13
14impl<T: Production> Production for OptionProd<T> {
15 type L = T::L;
16 #[inline]
17 fn debug() -> Cow<'static, str> {
18 let inner = T::debug();
19 if let Some(rest) = inner.strip_prefix('(') {
20 if let Some(inner) = rest.strip_suffix(")+") {
21 return Cow::Owned(format!("({inner})*"));
22 }
23 if let Some(inner) = rest.strip_suffix("]+") {
24 return Cow::Owned(format!("({inner}]*"));
25 }
26 }
27 Cow::Owned(format!("({})?", T::debug()))
28 }
29
30 fn register(meta: &mut MetadataBuilder<Self::L>) {
31 crate::register_union!(meta, T, Epsilon<T::L>)
32 }
33}
34
35#[derive(Node, ToSpan, Clone, PartialEq)]
37#[doc(alias = "Option")]
38pub struct Optional<T: Produce>(pub Node<Option<T>>);
39
40impl<T: std::fmt::Debug + Produce> std::fmt::Debug for Optional<T> {
41 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42 match &self.0.value {
43 Some(node) => f.debug_tuple("Some").field(&node).finish(),
44 None => f.debug_tuple("None").field(&self.0.span).finish(),
45 }
46 }
47}
48
49impl<T: Produce> Produce for Optional<T> {
50 type Prod = OptionProd<T::Prod>;
51 fn produce(
52 parser: &mut Parser<'_, <Self::Prod as Production>::L>,
53 meta: &Metadata<<Self::Prod as Production>::L>,
54 ) -> SynResult<Self, <Self::Prod as Production>::L> {
55 produce_option(parser, meta, |x| x).map(Self::from)
56 }
57}
58
59#[derive(Node, ToSpan, Clone, PartialEq)]
61pub struct Exists<T: Produce>(Node<bool>, PhantomData<T>);
62
63impl<T: Produce> std::fmt::Debug for Exists<T> {
64 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
65 self.0.fmt(f)
66 }
67}
68
69impl<T: Produce> Produce for Exists<T> {
70 type Prod = OptionProd<T::Prod>;
71 fn produce(
72 parser: &mut Parser<'_, <Self::Prod as Production>::L>,
73 meta: &Metadata<<Self::Prod as Production>::L>,
74 ) -> SynResult<Self, <Self::Prod as Production>::L> {
75 produce_option(parser, meta, |x: Option<T>| x.is_some()).map(Self::from)
76 }
77}
78fn produce_option<T, O, F: FnOnce(Option<T>) -> O, L: Lexicon>(
79 parser: &mut Parser<'_, L>,
80 meta: &Metadata<L>,
81 f: F,
82) -> SynResult<Node<O>, L>
83where
84 T: Produce + ToSpan,
85 T::Prod: Production<L = L>,
86{
87 let token = parser.peek_token_src();
88 if token.is_none() {
89 return SynResult::Success(Node::new(parser.empty_span(), f(None)));
91 }
92 let first = meta.first.get(&T::prod_id());
93 if !first.contains(token) {
94 return SynResult::Success(Node::new(parser.empty_span(), f(None)));
96 }
97 match T::produce(parser, meta) {
99 SynResult::Success(t) => SynResult::Success(Node::new(t.span(), f(Some(t)))),
100 SynResult::Recovered(t, error) => {
101 SynResult::Recovered(Node::new(t.span(), f(Some(t))), error)
102 }
103 SynResult::Panic(error) => {
104 SynResult::Recovered(Node::new(parser.empty_span(), f(None)), error)
105 }
106 }
107}
108
109#[cfg(test)]
110mod tests {
111 use crate::prelude::*;
112 use crate::GrammarError;
113
114 use crate::test::prelude::*;
115 use crate::test::{Ident, OpAdd};
116
117 #[derive_syntax]
118 #[teleparse(root)]
119 #[derive(Debug, PartialEq, Clone)]
120 struct OptIdent(tp::Option<Ident>);
121
122 #[test]
123 fn test_none() -> Result<(), GrammarError> {
124 let t = OptIdent::parse("+")?.unwrap();
125 let t_str = format!("{:?}", t.0);
126 assert_eq!(t_str, "None(0)");
127 assert_eq!(t, OptIdent(Node::new(0..0, None).into()));
128
129 Ok(())
130 }
131
132 #[test]
133 fn test_some() {
134 let t = OptIdent::parse("a").unwrap().unwrap();
135 let t_str = format!("{:?}", t.0);
136 assert_eq!(t_str, "Some(token Ident(0..1))");
137 assert_eq!(
138 t,
139 OptIdent(Node::new(0..1, Some(Ident::from_span(0..1))).into())
140 );
141 }
142
143 #[test]
144 fn test_use_as_option() -> Result<(), GrammarError> {
145 let t = OptIdent::parse("a")?.unwrap();
146 assert!(t.0.is_some());
147
148 Ok(())
149 }
150
151 #[derive_syntax]
152 #[teleparse(root, no_test)]
153 struct Seq(tp::Option<OpAdd>, OpAdd);
154
155 #[test]
156 fn test_seq_not_ll1() {
157 assert_not_ll1!(
158 Seq,
159 GrammarError::FirstFollowSeqConflict(
160 "Seq".to_string(),
161 "(+)?".to_string(),
162 "+".to_string(),
163 "\"+\"".to_string()
164 )
165 );
166 }
167
168 #[derive_syntax]
169 #[teleparse(root)]
170 #[derive(Debug, PartialEq, Clone)]
171 struct Seq2(OpAdd, tp::Option<OpAdd>);
172
173 #[test]
174 fn test_seq2() -> Result<(), GrammarError> {
175 let t = Seq2::parse("+ ")?.unwrap();
176 assert_eq!(
177 t,
178 Seq2(OpAdd::from_span(0..1), Node::new(1..1, None).into())
179 );
180
181 Ok(())
182 }
183
184 #[derive_syntax]
185 #[teleparse(root, no_test)]
186 struct Nested(super::Optional<super::Optional<Ident>>);
187
188 #[test]
189 fn test_nested_not_ll1() {
190 assert_not_ll1!(
191 Nested,
192 GrammarError::FirstFirstConflict(
193 "((Ident)?)?".to_string(),
194 "(Ident)?".to_string(),
195 "()".to_string(),
196 "<empty>".to_string(),
197 )
198 );
199 }
200
201 #[derive_syntax]
202 #[teleparse(root)]
203 #[derive(Debug, PartialEq, Clone)]
204 struct ExistIdent(tp::Exists<Ident>);
205
206 #[test]
207 #[allow(clippy::bool_assert_comparison)]
208 fn parse_exist() {
209 let t = ExistIdent::parse("a").unwrap().unwrap();
210 let t_str = format!("{:?}", t.0);
211 assert_eq!(t_str, "0..1 => true");
212 assert_eq!(t, ExistIdent(Node::new(0..1, true).into()));
213 assert_eq!(*t.0, true);
214
215 let t = ExistIdent::parse("+").unwrap().unwrap();
216 let t_str = format!("{:?}", t.0);
217 assert_eq!(t_str, "0 => false");
218 assert_eq!(t, ExistIdent(Node::new(0..0, false).into()));
219 assert_eq!(*t.0, false);
220 }
221}