binator_core/
parse.rs

1use core::{
2  fmt::Debug,
3  ops::BitOr,
4};
5
6use crate::{
7  Parsed,
8  Streaming,
9  Success,
10};
11
12/// Parse is a trait that all parsers should implement.
13/// There is a blanked implementation for type that implement FnMut that match
14/// signature of parse(). This mean you can quickly use a function to implement
15/// a Parser.
16pub trait Parse<Stream, Context> {
17  /// Token is what the parser produced.
18  /// For example, a parser that read an u32 would have as Token u32.
19  type Token; //: Debug;
20
21  /// The main method of binator, any parser will be called by this method.
22  /// `parse()` will take a stream as parameter and eat data from it to produce
23  /// a Token. The result is what the parser `Parsed` is an enum of possible
24  /// outcome.
25  fn parse(&mut self, stream: Stream) -> Parsed<Self::Token, Stream, Context>;
26}
27
28impl<Token, Stream, Context, F> Parse<Stream, Context> for F
29where
30  F: FnMut(Stream) -> Parsed<Token, Stream, Context>,
31{
32  type Token = Token;
33
34  fn parse(&mut self, stream: Stream) -> Parsed<Token, Stream, Context> {
35    self(stream)
36  }
37}
38
39// Array: Behavior chained "or"
40
41// const fn non_zero(n: usize) -> usize {
42//   if n == 0 {
43//     panic!("Parse empty array don't make sense")
44//   } else {
45//     n
46//   }
47// }
48
49/// Array can be used to try several parser until one succeed.
50/// The parser are tried from start to end of the array.
51/// This is limited to parser of the same type.
52impl<Stream, Context, Parser, const N: usize> Parse<Stream, Context> for [Parser; N]
53where
54  Stream: Streaming,
55  Parser: Parse<Stream, Context>,
56  Context: BitOr<Output = Context>,
57  //  [(); non_zero(N)]:,
58{
59  type Token = Parser::Token;
60
61  fn parse(&mut self, stream: Stream) -> Parsed<Self::Token, Stream, Context> {
62    let mut iter = self.iter_mut();
63
64    if let Some(first) = iter.next() {
65      match first.parse(stream.clone()) {
66        success @ Parsed::Success { .. } => success,
67        Parsed::Failure(context) => {
68          let mut acc = context;
69
70          for parser in iter {
71            match parser.parse(stream.clone()) {
72              success @ Parsed::Success { .. } => {
73                return success;
74              }
75              Parsed::Failure(context) => {
76                acc = acc.bitor(context);
77              }
78              Parsed::Error(context) => {
79                return Parsed::Error(acc.bitor(context));
80              }
81            }
82          }
83
84          Parsed::Failure(acc)
85        }
86        Parsed::Error(context) => Parsed::Error(context),
87      }
88    } else {
89      panic!("Parse empty array don't make sense")
90    }
91  }
92}
93
94// Tuple: Behavior chained "and"
95include!(concat!(env!("OUT_DIR"), "/parse_tuple.rs"));
96
97impl<Stream, Context> Parse<Stream, Context> for () {
98  type Token = ();
99
100  fn parse(&mut self, stream: Stream) -> Parsed<(), Stream, Context> {
101    Parsed::new_success((), stream)
102  }
103}
104
105#[cfg(test)]
106mod tests {
107  use core::ops::BitOr;
108
109  use crate::{
110    Parse,
111    Parsed,
112    Streaming,
113  };
114
115  // Should not compile
116  #[allow(dead_code)]
117  fn array_parse_zero<Stream, Context>(stream: Stream) -> Parsed<(), Stream, Context>
118  where
119    Stream: Streaming,
120    <Stream as Streaming>::Item: Into<char>,
121    Context: BitOr<Output = Context>,
122  {
123    let mut foo: [(); 0] = [];
124    Parse::<Stream, Context>::parse(&mut foo, stream)
125  }
126}
127
128#[cfg(feature = "either")]
129impl<Stream, Context, L, R> Parse<Stream, Context> for either::Either<L, R>
130where
131  L: Parse<Stream, Context>,
132  R: Parse<Stream, Context, Token = L::Token>,
133{
134  type Token = L::Token;
135
136  fn parse(&mut self, stream: Stream) -> Parsed<Self::Token, Stream, Context> {
137    match self {
138      either::Either::Left(l) => l.parse(stream),
139      either::Either::Right(r) => r.parse(stream),
140    }
141  }
142}