noa_parser/
acceptor.rs

1use crate::errors::{ParseError, ParseResult};
2use crate::scanner::Scanner;
3use crate::visitor::Visitor;
4
5/// A type that wraps a `Scanner` and holds a successfully accepted value.
6///
7/// When a value is successfully accepted, the `Acceptor` stores the value in its
8/// `data` field and returns itself. If a value is not accepted, the `Acceptor`
9/// rewinds the scanner to the previous position and returns itself.
10///
11/// # Type Parameters
12///
13/// * `T` - The type of the data to scan.
14/// * `V` - The type of the value to accept.
15/// * `'a` - The lifetime of the data to scan.
16/// * `'b` - The lifetime of the acceptor.
17#[derive(Debug)]
18pub struct Acceptor<'a, 'b, T, V> {
19    /// The accepted value, if any.
20    data: Option<V>,
21    /// The scanner to use when consuming input.
22    scanner: &'b mut Scanner<'a, T>,
23}
24
25impl<'a, 'b, T, V> Acceptor<'a, 'b, T, V> {
26    /// Create a new acceptor.
27    ///
28    /// # Arguments
29    ///
30    /// * `scanner` - The scanner to use when consuming input.
31    ///
32    /// # Returns
33    ///
34    /// A new acceptor that uses the given scanner.
35    pub fn new(scanner: &'b mut Scanner<'a, T>) -> Acceptor<'a, 'b, T, V> {
36        Acceptor {
37            data: None,
38            scanner,
39        }
40    }
41}
42
43impl<'a, T, V> Acceptor<'a, '_, T, V> {
44    /// Attempt to accept a `U` using the given `transformer`, and rewind the scanner
45    /// and return the current acceptor if it fails.
46    ///
47    /// # Arguments
48    ///
49    /// * `transformer` - A function that takes a `U` and returns a `ParseResult<V>`.
50    ///
51    /// # Returns
52    ///
53    /// If the `U` is successfully accepted and the `transformer` returns `Ok`, returns
54    /// the current acceptor with the resulting value in `data`. If the `U` is not
55    /// successfully accepted, returns the current acceptor with the current position
56    /// of the scanner rewound to the position at which the `U` was attempted, and
57    /// `data` is left `None`.
58    pub fn try_or<U: Visitor<'a, T>, F>(mut self, transformer: F) -> ParseResult<Self>
59    where
60        F: Fn(U) -> V,
61    {
62        let cursor = self.scanner.current_position();
63        // Propagate the data
64        if self.data.is_some() {
65            return Ok(self);
66        }
67
68        match U::accept(self.scanner) {
69            Ok(found) => {
70                self.data = Some(transformer(found));
71            }
72            Err(ParseError::UnexpectedToken) => {
73                self.scanner.jump_to(cursor);
74            }
75            Err(err) => {
76                return Err(err);
77            }
78        }
79
80        Ok(self)
81    }
82
83    /// Consume the acceptor and return the `V` that was accepted if the acceptor was
84    /// successful.
85    ///
86    /// # Returns
87    ///
88    /// If the acceptor was successful (i.e., `data` is `Some`), returns the `V` that
89    /// was accepted. Otherwise, returns `None`.
90    pub fn finish(self) -> Option<V> {
91        self.data
92    }
93}