parser_fuck/combinators/
or.rs1use crate::*;
2use std::marker::PhantomData;
3
4#[derive(Debug, PartialEq, Eq, Clone)]
6pub struct Or<A, B, I = ()> {
7 a: A,
8 b: B,
9 _i: PhantomData<I>,
10}
11impl<I: TimeTravel, A, B> Or<A, B, I>
12where
13 A: Parser<I>,
14 B: Parser<I, Output = A::Output>,
15{
16 #[inline]
17 pub fn new(a: A, b: B) -> Self {
18 Self {
19 a,
20 b,
21 _i: PhantomData,
22 }
23 }
24}
25impl<I: TimeTravel, A, B> Parser<I> for Or<A, B, I>
26where
27 A: Parser<I>,
28 B: Parser<I, Output = A::Output>,
29{
30 type Output = A::Output;
31
32 fn parse(&self, mut input: I) -> Option<Self::Output> {
33 let from = input.save();
34 let a = self.a.parse(input.ref_clone());
35 a.or_else(|| {
36 input.back(from);
37 let b = self.b.parse(input);
38 b
39 })
40 }
41}
42
43#[macro_export]
44#[doc(hidden)]
45macro_rules! _or {
46 { $input:ident, $from:ident ; $a:expr, $b: expr } => {
47 $a.parse($input.ref_clone()).or_else(|| {
48 $input.back($from);
49 $b.parse($input)
50 })
51 };
52 { $input:ident, $from:ident ; $a:expr, $($b: expr),+ } => {
53 $a.parse($input.ref_clone()).or_else(|| {
54 $input.back($from);
55 _or!($input, $from ; $($b),+)
56 })
57 }
58}
59#[macro_export(local_inner_macros)]
68macro_rules! or {
69 { } => {{ }};
70 { $input:expr } => {{ }};
71 { $input:expr ; } => {{ }};
72 { $input:expr ; $a:expr $(,)? } => {{
73 $a.parse($input)
74 }};
75 { $input:expr ; $a:expr, $($b: expr),+ $(,)? } => {{
76 let mut input = $input;
77 let from = input.save();
78 _or!(input, from ; $a, $($b),+)
79 }};
80}
81
82#[cfg(test)]
83mod tests {
84 use crate::*;
85
86 #[test]
87 fn test_macro() {
88 let code = "b";
89 let span = code.span();
90
91 let r = or!(span ; one('a'), one('b'), one('c'));
92 println!("{:?}", r);
93 assert_eq!(r, Some(0..1));
94 }
95
96 #[test]
97 fn test() {
98 let code = "asd";
99 let span = code.span();
100 let a = substr("b");
101 let b = substr("a");
102 let x = a.or(b);
103
104 let r = x.parse(span);
105 println!("{:?}", r);
106 assert_eq!(r, Some(0..1));
107 }
108
109 #[test]
110 fn test_a() {
111 let code = "asd";
112 let span = code.span();
113 let a = substr("a");
114 let b = substr("b");
115 let x = a.or(b);
116
117 let r = x.parse(span);
118 println!("{:?}", r);
119 assert_eq!(r, Some(0..1));
120 }
121
122 #[test]
123 fn test_none() {
124 let code = "asd";
125 let span = code.span();
126 let a = substr("b");
127 let b = substr("c");
128 let x = a.or(b);
129
130 let r = x.parse(span);
131 println!("{:?}", r);
132 assert_eq!(r, None);
133 }
134}