feat: add optional modifier.

This commit is contained in:
jackfiled 2024-11-27 22:03:05 +08:00
parent 3e6c2c9bde
commit 9da7290da5
2 changed files with 41 additions and 1 deletions

View File

@ -3,7 +3,7 @@ mod primitive_parsers;
use crate::parser::modified_parsers::{ use crate::parser::modified_parsers::{
BindParser, ConvertParser, LitervalCountParser, LitervalParser, LookAheadParser, MapParser, BindParser, ConvertParser, LitervalCountParser, LitervalParser, LookAheadParser, MapParser,
NextParser, ReverseParser, TryParser, NextParser, OptionalParser, ReverseParser, TryParser,
}; };
use crate::parser::primitive_parsers::{ use crate::parser::primitive_parsers::{
AnyParser, FailParser, FailWithMessageParser, SatifiedMapParser, SatisfyParser, SkipParser, AnyParser, FailParser, FailWithMessageParser, SatifiedMapParser, SatisfyParser, SkipParser,
@ -200,6 +200,13 @@ where
phantom_data: PhantomData, phantom_data: PhantomData,
} }
} }
fn optional(self) -> OptionalParser<Self>
where
Self: Sized,
{
OptionalParser { parser: self }
}
} }
impl<'a, TToken, T: 'a, TContext, F> Parser<'a, TToken, T, TContext> for F impl<'a, TToken, T: 'a, TContext, F> Parser<'a, TToken, T, TContext> for F

View File

@ -240,6 +240,27 @@ where
} }
} }
pub struct OptionalParser<P> {
pub(crate) parser: P,
}
impl<'a, TToken, T: 'a, TContext, P> Parser<'a, TToken, Option<T>, TContext> for OptionalParser<P>
where
TToken: Debug + Clone,
P: Parser<'a, TToken, T, TContext>,
{
fn parse(
&self,
context: Rc<RefCell<ParserContext<TToken, TContext>>>,
input: &'a [TToken],
) -> ParserResult<'a, TToken, Option<T>> {
match self.parser.parse(context, input) {
Ok(r) => Ok((r.0, Some(r.1))),
Err(r) => Ok((r.input, None)),
}
}
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
@ -414,4 +435,16 @@ mod test {
char_parser('a').reverse(()).parse(c, i) char_parser('a').reverse(()).parse(c, i)
}); });
} }
#[test]
fn optional_test() {
parser_test_helper(
ParserContext::new_with_str("abc", ()),
&Some('a'),
|c, i| char_parser('a').optional().parse(c, i),
);
parser_test_helper(ParserContext::new_with_str("bc", ()), &None, |c, i| {
char_parser('a').optional().parse(c, i)
});
}
} }